Tokens

儘管設置和初始化了實現,但代理呼叫都在測試套件中恢復

  • July 6, 2020

我目前正在使用非結構化數據代理模型和 ERC20 代幣實現(類似於 USDC)編寫可升級合約。

這意味著傳統的方法是將事務發送到代理並觸發回退功能(除非您是管理員)並將呼叫委託給實現,同時將狀態儲存在代理中。

目前,我正在編寫一個測試套件,它部署兩個契約並通過代理設置實現的初始化功能。

我遇到了一個錯誤,無論我給代理什麼呼叫,無論是通過“symbol()”請求符號還是請求鑄幣者角色,它總是會恢復(但不應該):

錯誤:返回錯誤:處理事務時出現 VM 異常:還原

如果我使用管理員密鑰,它會正確失敗:

錯誤:返回錯誤:處理事務時出現 VM 異常:revert 無法從代理管理員呼叫回退函式

但是,在呼叫實現中定義的函式時,它不應該恢復。我的這個測試程式碼如下:

const { accounts, contract, web3 } = require('@openzeppelin/test-environment');
const [ admin, user, recipient ] = accounts;
// Loads the built artifact from build/contracts/ERC20.json
const ERC20 = contract.fromArtifact('ERC20');
const Proxy = contract.fromArtifact('Proxy');
// test framework
const { expect } = require('chai');
//erc20 generic tests
const shouldBehaveLikeErc20 = require("./behaviors/ERC20.behavior.js");
const shouldBehaveLikeErc20Detailed = require("./behaviors/ERC20Detailed.behavior.js");

describe('ERC20', function () {

   const name = 'ERC20';
   const symbol = 'ERC20';
   const decimals = 18;
   const totalSupply = web3.utils.toBN("1e28");

   beforeEach(async function() {
       this.ERC20 = await ERC20.new();
       this.ERC20V2 = await ERC20.new();
       let data = web3.eth.abi.encodeFunctionSignature('initialize()');
       this.Proxy = await Proxy.new(this.ERC20.address, admin, data, { from: admin });
   });

   it("should behave like ERC20", function() {
       //need ERC20 ABI with Proxy address as Proxy delegates
       this.token = this.ERC20;
       this.token.address = this.Proxy.address;
       shouldBehaveLikeErc20(accounts, totalSupply);
       shouldBehaveLikeErc20Detailed(name, symbol, decimals)
   });

   it('the deployer is the minter', async function () {
       let abi = {
               "constant": true,
               "inputs": [
                   {
                       "internalType": "address",
                       "name": "account",
                       "type": "address"
                   }
               ],
               "name": "isMinter",
               "outputs": [
                   {
                       "internalType": "bool",
                       "name": "",
                       "type": "bool"
                   }
               ],
               "payable": false,
               "stateMutability": "view",
               "type": "function"
           };
       let functionData = web3.eth.abi.encodeFunctionCall(abi, [ admin ]);
       //always reverts here, but it shouldn't 
       let result = await web3.eth.call({
           from: user,
           to: this.Proxy.address,
           functionData
       });
       expect(web3.eth.abi.decodeParameter('bool', result)).to.equal(true);
   });

   it('upgrades the implementation address', async function () {
       await this.Proxy.upgradeTo(this.ERC20V2.address, { from: admin });
   });

});

傻我,我忘了包括數據對象鍵……

let result = await web3.eth.call({
           from: user,
           to: this.MyContract.address,
           data: functionData //forgot data:
       });

引用自:https://ethereum.stackexchange.com/questions/84797