Simple question, but I couldn’t figure the answer.
Are there plans/EIP to use the second parameter of DELEGATECALL
? Or am I wrong (in which case the parameter isn’t ignored) ?
In c++ Ethereum evm lies this code :
if (m_ext->balance(m_ext->myAddress) >= callParams->valueTransfer && m_ext->depth < 1024)
{
callParams->onOp = m_onOp;
callParams->senderAddress = m_OP == Instruction::DELEGATECALL ? m_ext->caller : m_ext->myAddress; // if Delegatecall the sender address and value stays the same
// STATICCALL is rejected by !m_schedule->haveStaticCall elsewhere
callParams->receiveAddress = (m_OP == Instruction::CALL || m_OP == Instruction::STATICCALL) ? callParams->codeAddress : m_ext->myAddress; // if opcode isn’t CALL, the target address to call is the current one.
callParams->data = bytesConstRef(m_mem.data() + inOff, inSize);
o_output = bytesRef(m_mem.data() + outOff, outSize);
return true;
}
return false;
and in Go Ethereum at execution.go :
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > callCreateDepthMax {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, errCallCreateDepth
}
snapshot := env.SnapshotDatabase()
var to vm.Account
if !env.Db().Exist(*toAddr) {
to = env.Db().CreateAccount(*toAddr)
} else {
to = env.Db().GetAccount(*toAddr)
}
// Iinitialise a new contract and make initialise the delegate values
contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
contract.SetCallCode(codeAddr, codeHash, code)
defer contract.Finalise()
ret, err = evm.Run(contract, input)
if err != nil {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshot)
}
return ret, addr, err
}
where .AsDelegate()
returns the caller address of the address which is to be DELEGATECALLED (and this is that address which is called at evm.Run
) :
// AsDelegate sets the contract to be a delegate call and returns the current
// contract (for chaining calls)
func (c *Contract) AsDelegate() *Contract {
c.DelegateCall = true
// NOTE: caller must, at all times be a contract. It should never happen
// that caller is something other than a Contract.
c.CallerAddress = c.caller.(*Contract).CallerAddress
return c
}
So while the target parameter is read from the stack, it is ignored at a later stage as shown in those references implementations.