Tokens
儘管設置和初始化了實現,但代理呼叫都在測試套件中恢復
我目前正在使用非結構化數據代理模型和 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: });