mirror of
https://github.com/autistic-symposium/web3-starter-sol.git
synced 2025-04-29 12:06:07 -04:00
63 lines
1.9 KiB
Solidity
63 lines
1.9 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.17;
|
|
|
|
// An example of calling multiple functions with a single transaction, using delegatecall.
|
|
|
|
contract MultiDelegatecall {
|
|
error DelegatecallFailed();
|
|
|
|
function multiDelegatecall(
|
|
bytes[] memory data
|
|
) external payable returns (bytes[] memory results) {
|
|
results = new bytes[](data.length);
|
|
|
|
for (uint i; i < data.length; i++) {
|
|
(bool ok, bytes memory res) = address(this).delegatecall(data[i]);
|
|
if (!ok) {
|
|
revert DelegatecallFailed();
|
|
}
|
|
results[i] = res;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Why use multi delegatecall? Why not multi call?
|
|
// alice -> multi call --- call ---> test (msg.sender = multi call)
|
|
// alice -> test --- delegatecall ---> test (msg.sender = alice)
|
|
contract TestMultiDelegatecall is MultiDelegatecall {
|
|
event Log(address caller, string func, uint i);
|
|
|
|
function func1(uint x, uint y) external {
|
|
// msg.sender = alice
|
|
emit Log(msg.sender, "func1", x + y);
|
|
}
|
|
|
|
function func2() external returns (uint) {
|
|
// msg.sender = alice
|
|
emit Log(msg.sender, "func2", 2);
|
|
return 111;
|
|
}
|
|
|
|
mapping(address => uint) public balanceOf;
|
|
|
|
// WARNING: unsafe code when used in combination with multi-delegatecall
|
|
// user can mint multiple times for the price of msg.value
|
|
function mint() external payable {
|
|
balanceOf[msg.sender] += msg.value;
|
|
}
|
|
}
|
|
|
|
contract Helper {
|
|
function getFunc1Data(uint x, uint y) external pure returns (bytes memory) {
|
|
return abi.encodeWithSelector(TestMultiDelegatecall.func1.selector, x, y);
|
|
}
|
|
|
|
function getFunc2Data() external pure returns (bytes memory) {
|
|
return abi.encodeWithSelector(TestMultiDelegatecall.func2.selector);
|
|
}
|
|
|
|
function getMintData() external pure returns (bytes memory) {
|
|
return abi.encodeWithSelector(TestMultiDelegatecall.mint.selector);
|
|
}
|
|
}
|