I would like to use delegatecall
to deposit ETH into WETH and batch this process together with other actions (see code below). When running truffle tests, it seems like the events are triggered correctly but the state does not seem to be updated.
Same behavior on the Rinkeby network. The weird thing is that the transaction completes completely successfully. Here is an example of transaction: https://rinkeby.etherscan.io/tx/0x93c724174e2b70f2257544ebc0e0b9da6e31a7a752872da7683711bd4d4bd92b
Solidity code:
pragma solidity 0.4.24;
import "../interfaces/ERC20.sol";
import "./WETH9.sol";
contract SetupAccount {
address public exchangeAddress;
address public wethAddress;
constructor (
address _exchangeAddress,
address _wethAddress
) public {
exchangeAddress = _exchangeAddress;
wethAddress = _wethAddress;
}
function setup(
address[] _tokenAddresses,
uint256[] _values
) public payable {
for (uint i = 0; i < _tokenAddresses.length; i++) {
_tokenAddresses[i].delegatecall(abi.encodeWithSignature("approve(address,uint256)", exchangeAddress, _values[i]));
}
if (msg.value != 0) {
wethAddress.delegatecall(abi.encodeWithSignature("deposit()"));
}
}
Failing truffle test:
describe('setupAccount', async () => {
beforeEach(async () => {
weth = await WETH.new()
exchange = await Exchange.new(rewardAccount)
bnb = await BNB.new(user1, 1000)
dai = await DAI.new(user1, 1000)
omg = await OMG.new(user1, 1000)
setupAccount = await SetupAccount.new(exchange.address, weth.address)
})
it('setupAccount should deposit weth and approve tokens', async () => {
await setupAccount.setup(
[bnb.address, dai.address, omg.address],
[1000, 1000, 1000],
{ from: user1, value: 10 ** 18 }
)
let wethBalance = await weth.balanceOf(user1)
wethBalance.should.be.bignumber.equal(10 ** 18)
bnbAllowance.should.be.bignumber.equal(1000)
daiAllowance.should.be.bignumber.equal(1000)
omgAllowance.should.be.bignumber.equal(1000)
})
})
Events emitted during test:
Events emitted during test:
---------------------------
Deposit(dst: <indexed>, wad: 1000000000000000000)
---------------------------
Test result:
1) Contract: SetupAccount
setupAccount
setupAccount should deposit weth and approve tokens:
AssertionError: expected '0' to equal '1000000000000000000'
+ expected - actual
-0
+1000000000000000000
I'm confused as to why this doesn't work. Thank's in advance.
msg.value
is preserved correctly through a delegatecall
. The following code demonstrates this, as evidenced by the emitted event showing the correct value.
pragma solidity >0.4.99 <0.6;
contract Target {
event Received(uint256 amount);
function deposit() external payable {
emit Received(msg.value);
}
}
contract Delegater {
function deposit() external payable {
(bool success,) = address(new Target()).delegatecall(abi.encodeWithSignature("deposit()"));
require(success);
}
}