создать обновляемый контракт прокси, который работает с MetaMask - PullRequest
0 голосов
/ 05 мая 2019

Я создаю прокси-контракт, который подключается к существующему 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) }
       }
   }
}

функция balanceOf работает нормально, когда я добавляю токен в метамаску с ERC-20 адресом контракта. но показать ноль по контракту с прокси

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

1 Ответ

0 голосов
/ 05 мая 2019

Контракт прокси работает немного по-другому.

let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)

DELEGATECALL в вашем прокси-контракте вызывает контракт по адресу, указанному в _impl. Таким образом, в результате он запускает код _impl (в вашем случае ERC20) в среде прокси-контрактов. В результате, хранилище прокси модифицируется, а не ERC20 заключает контракт на хранение. Ссылка на то, как делегат работает .

Поэтому я бы хотел посмотреть, как вы инициализируете свой контракт ERC20 и устанавливаете его баланс.

Вы должны сделать что-то вроде этого

erc20Contract = await erc20Contract.at(proxy.address)

erc20Contract.initialize()

Первая строка дает вам интерфейс erc20Contract по адресу контракта с прокси. А вторая строка будет переделывать работу конструктора по адресу и хранилищу прокси-контракта.

...