-
Notifications
You must be signed in to change notification settings - Fork 4
06. Delegate
Claim ownership of the contract.
The Delegation fallback implements a delegatecall.
By sending the right msg.data we can trigger the function pwn() of the Delegate contract.
Since this function is executed by a delegatecall the context will be preserved:
owner = msg.sender = address of contract that send data to the Delegation fallback (attacker contract)
There are several ways to interact with other contracts from within a given contract.
If the ABI (like an API for smart contracts) and the contract's address are known, we can simply instantiate (e.g with a contract interface) the contract and call its functions.
contract Called {
function fun() public returns (bool);
}
contract Caller {
Called public called;
constructor (Called addr) public {
called = addr;
}
function call () {
called.fun();
}
}
Calling a function means injecting a specific context (arguments) to a group of commands (function) and commands are executing one by one with this context.
In Ethereum, a function call can be expressed by a 2 parts bytecode as long as 4 + 32 * N bytes.
- Function Selector: first 4 bytes of function callβs bytecode.
Generated by hashing target functionβs name plus with the type of its arguments
excluding empty space. Ethereum uses keccak-256 hashing function to create function selectors:
functionSelectorHash = web3.utils.keccak256('func()') - Function Argument: convert each value of arguments into a hex string padded to 32 bytes.
If there is more than one argument, they are concatenated.
In Solidity encoding the function selector together with the arguments can be done with globally available encoding/decoding functions: e.g.
abi.encodeWithSignature("add(uint256,uint256)", valueForArg1, valueForArg2)
Can be used to invoke public functions by sending data in a transaction.
contractInstance.call(bytes4(keccak256("functionName(inputType)"))
DelegateCall: preserves context
contractInstance.delegatecall(bytes4(keccak256("functionName(inputType)"))
Delegate calls preserve current calling contract's context (storage, msg.sender, msg.value).
The calling contract using delegate calls allows the called contract to mutate its state.
- Compute the encoded hash that will be used for
msg.data - Send
msg.datain a transaction to the contract fallback
- Use the higher level
call()function to inherit from libraries, especially when you donβt need to change contract storage and do not care about gas control. - When inheriting from a library intending to alter your contractβs storage, make sure to line up your storage slots with the libraryβs storage slots to avoid unexpected state changes..
- Authenticate and do conditional checks on functions that invoke
delegatecalls.


