G'day, mates!
While I'm testing Strings.sol library, I got an error with TypeError: uniqueNames[name_1].push is not a function.
contracts
library Strings {
function toString(uint256 value) public pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
}
testing script
const { expect, assert } = require("chai");
const { ethers } = require("hardhat");
describe("Library Test", function () {
let Test, test, owner, addr1;
beforeEach(async function () {
Test = await ethers.getContractFactory("Strings");
[owner, addr1] = await ethers.getSigners();
test = await Test.deploy();
})
it("Strings test", async function () {
const t1 = await test.toString(123); //error point
console.log(t1);
});
});
I changed a function name from toString to toStrin just for testing. and it works.
function toString(uint256 value) public
function toStrin(uint256 value) public
&
const t1 = await test.toStrin(123);
So I thought it's because js has the function with the same name.
But although I tried callStatic function to override the js function, it still didn't work.
const t1 = await test.callStatic["toString(uint256)"](123);
repeatedly same error
TypeError: uniqueNames[name_1].push is not a function.
But expectedly const t1 = await test.callStatic["toStrin(uint256)"](123); with function function toStrin(uint256 value) public worked.
I may need to use Object.hasOwnProperty internally, as I might be using a null check. I鈥檒l look into this as soon as possible.
Thanks, just happened to me yesterday, blame the SO: https://ethereum.stackexchange.com/a/58341/1210 .'-D
Hope there is some way around this, even explicit warning would be enough.
This code was intended to be used as an internal library, not as a public methods :)
I ran into a similar issue with a contract function overloading a js object property (valueOf).
@ricmoo this diff should fix the issue. unfortunately i can't open a PR with it right now.
commit 6bbc63c92298ac7263450a11067c4331665dbfc5 (HEAD -> master)
Author: Tarrence van As <[email protected]>
Date: Mon Jun 7 06:46:42 2021 -0700
fix(contracts): solidity function names conflicting with js object property names
diff --git a/packages/contracts/src.ts/index.ts b/packages/contracts/src.ts/index.ts
index bec415f7..bc34b2bb 100644
--- a/packages/contracts/src.ts/index.ts
+++ b/packages/contracts/src.ts/index.ts
@@ -685,7 +685,7 @@ export class BaseContract {
}
}
- const uniqueNames: { [ name: string ]: Array<string> } = { };
+ const uniqueNames = new Map<string, Array<string>>();
const uniqueSignatures: { [ signature: string ]: boolean } = { };
Object.keys(this.interface.functions).forEach((signature) => {
const fragment = this.interface.functions[signature];
@@ -702,8 +702,8 @@ export class BaseContract {
// are ambiguous
{
const name = fragment.name;
- if (!uniqueNames[name]) { uniqueNames[name] = [ ]; }
- uniqueNames[name].push(signature);
+ if (!uniqueNames.has(name)) { uniqueNames.set(name, [ ]) }
+ uniqueNames.get(name).push(signature);
}
if ((<Contract>this)[signature] == null) {
@@ -730,10 +730,8 @@ export class BaseContract {
}
});
- Object.keys(uniqueNames).forEach((name) => {
-
+ uniqueNames.forEach((signatures, name) => {
// Ambiguous names to not get attached as bare names
- const signatures = uniqueNames[name];
if (signatures.length > 1) { return; }
const signature = signatures[0];
Most helpful comment
This code was intended to be used as an internal library, not as a public methods :)