我正在创建一个连接到现有ERC-20
合同的代理合同。
该代理合同应能够与元掩码连接并显示令牌余额。
在带有代理地址的元掩码中添加令牌时,一切正常,它正确显示符号和十进制数字,但不平衡。显示为零。
代理合同代码:
contract Proxy {
address private _implementation;
event Upgraded(address indexed implementation);
function implementation() public view returns (address) {
return _implementation;
}
function upgradeTo(address impl) public {
_implementation = impl;
emit Upgraded(impl);
}
function () payable external {
address _impl = implementation();
require(_impl != address(0));
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize)
let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
let size := returndatasize
returndatacopy(ptr, 0, size)
switch result
case 0 { revert(ptr, size) }
default { return(ptr, size) }
}
}
}
当我在带有ERC-20
合约地址的metamask中添加令牌时,函数 balanceOf 工作正常。但按代理合同应显示为零
function balanceOf(address tokenOwner) public view returns (uint256) {
return balances[tokenOwner];
}
我的努力
为了测试,我编写了此函数:
function test(address theAddress) public view returns (address) {
return theAddress ;
}
当我调用参数'0xC357c241b98B15B3A08aeC3AcD49fBC0cbD74fcE'
时
ERC-20
合约上的返回相同地址,但代理人返回
此值:
0xc357c241b98b19150f7f8f1d47ad1cd500000000
我做的另一项测试是该功能:
function test2(string memory theString) public view returns (string memory) {
return theString ;
}
此功能在代理合同和ERC-20
合同上均可正常使用!
谢谢。
编辑1
我的web3.js
测试
var interval ;
document.addEventListener('DOMContentLoaded', function() {
interval = setInterval(run , 1000);
}, false);
function run(){
web3 = new Web3(web3.currentProvider);
console.log("call");
if(web3.eth.accounts[0] === undefined)
return;
clearInterval(interval);
console.log(web3.eth.accounts[0]);
web3.eth.defaultAccount = web3.eth.accounts[0];
var CoursetroContract = web3.eth.contract( JSON.parse(`[
{
"constant": true,
"inputs": [
{
"name": "theAddress",
"type": "address"
}
],
"name": "test",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "theString",
"type": "string"
}
],
"name": "test2",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]`));
var contract = CoursetroContract.at('0xd3744cac3a2f796c16b45e5be582c1c5f3039482'); //proxy
//var contract = CoursetroContract.at('0xd025c8835b2a4bd2f9eeb1d682db224f7b301868'); //erc20
contract.test(0xC357c241b98B15B3A08aeC3AcD49fBC0cbD74fcE,
function(err,result){
console.log("err" ,err);
console.log("result" , result);
}
);
编辑2
此合同地址已经在Ropsten Testnet
答案 0 :(得分:0)
代理合同的工作方式略有不同。
let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
代理合同中的 DELEGATECALL
通过_impl
中指定的地址调用合同。因此,结果是,它在代理合同的环境中运行_impl代码(在您的情况下为ERC20)。结果,修改了代理的存储,而不是ERC20签约存储。链接至delegatecall works。
所以我的建议是看看您如何初始化ERC20合同并设置其余额。
您将必须执行类似的操作
erc20Contract = await erc20Contract.at(proxy.address)
erc20Contract.initialize()
第一行为您提供erc20Contract的接口,位于代理合同的地址处。 第二行将在代理合同的地址和存储处重做构造函数的工作。