合约调用合约有下面4种方式: CALL CALLCODE DELEGATECALL STATICCALL 8.1 CALL vs. CALLCODE CALL和CALLCODE的区别在于:代码执行的上下文环境不同。 具体来说,CALL修改的是被调用者的storage,而CALLCODE修改的是调用者的storage。 ? 我们再调用一下inc_callcode()试试: ? 可以发现,这次修改的是合约A中x,合约B中的x保持不变。 8.2 CALLCODE vs. DELEGATECALL 实际上,可以认为DELEGATECALL是CALLCODE的一个bugfix版本,官方已经不建议使用CALLCODE了。 CALLCODE和DELEGATECALL的区别在于:msg.sender不同。 具体来说,DELEGATECALL会一直使用原始调用者的地址,而CALLCODE不会。 ?
returns (string resMes){testMem--;resMes = "try to modify testMem and has constant label";}}内部调用: call,callcode 除了直接调用函数,还可以通过call,callcode,delegatecall的方式调用其他合约的函数,区别如下:CALL:是在 被调用者 的上下文中执行,只能修改被调用者的storage;CALLCODE 和DELEGATECALL: 是在 调用者 的上下文中执行, 可以修改调用者的storage;CALLCODE 阻止msg.sender和msg.value传递; 而DELEGATECALL不阻止;在A 的函数中,B.callcode(c的函数): c看到msg.sender是B;在A的函数中,B.delegatecall(c的函数): c看到msg.sender是A;合约示例如下:contract D (uint256)")), _n); } function callcodeSetN(address _e, uint _n) { // D的 storage被修改, E未修改 _e.callcode
=== PAUSE TestState/stEWASMTests/callCode.json === CONT TestState/stEWASMTests/callCode.json -- - FAIL: TestState/stEWASMTests/callCode.json (0.03s) === RUN TestState/stEWASMTests/callCode.json/Byzantium === PAUSE TestState/stEWASMTests/callCode.json === CONT TestState/stEWASMTests/callCode.json -- - PASS: TestState/stEWASMTests/callCode.json (0.46s) === RUN TestState/stEWASMTests/callCode.json/Byzantium [1] storageStore 0 20 [0] storageStore 80 60 --- PASS: TestState/stEWASMTests/callCode.json/
call(), callcode() 和 delegatecall() 函数 为了和非ABI协议的合约进行交互,可以使用call() 函数, 它用来向另一个合约发送原始数据,支持任何类型任意数量的参数, 在homestead阶段之前,仅有一个受限的callcode()方法可用,但callcode未提供对msg.sender,msg.value的访问权限。 上面的这三个方法call(),delegatecall(),callcode()都是底层的消息传递调用,最好仅在万不得已才进行使用,因为他们破坏了Solidity的类型安全。 .gas() 在call(), callcode() 和 delegatecall() 函数下都可以使用, delegatecall()不支持.value() 注解:所有合约都继承了address的成员 callcode不鼓励使用,以后会移除。 警告:上述的函数都是底层的函数,使用时要异常小心。
在 Solidity 中提供了 call、delegatecall、callcode 三个函数来实现合约之间相互调用及交互。 由此本文主要是针对 Solidity 合约调用函数call、delegatecall、callcode 三种调用方式的异同、滥用导致的漏洞模型并结合实际案例进行分析介绍。 callcode: 调用后内置变量 msg 的值会修改为调用者,但执行环境为调用者的运行环境。 0x04 callcode 安全问题 callcode: 调用后内置变量 msg 的值会修改为调用者,但执行环境为调用者的运行环境。 存在的安全问题将同时存在于 callcode 中,这里不再进行详细的分析。
在 Solidity 中提供了 call、delegatecall、callcode 三个函数来实现合约之间相互调用及交互。 由此本文主要是针对 Solidity 合约调用函数call、delegatecall、callcode 三种调用方式的异同、滥用导致的漏洞模型并结合实际案例进行分析介绍。 callcode: 调用后内置变量 msg 的值会修改为调用者,但执行环境为调用者的运行环境。 0x04 callcode 安全问题 callcode: 调用后内置变量 msg 的值会修改为调用者,但执行环境为调用者的运行环境。 存在的安全问题将同时存在于 callcode 中,这里不再进行详细的分析。
Solidity[4]有三种合约间的调用方式 call、delegatecall 和 callcode。其中,delegatecall可作为智能合约升级的一个较好的途径。 关于合约间的调用方式 call、delegatecall 和 callcode,详见我另一篇文章<<图文并茂详细介绍Solidity的三种合约间的调用方式 call、delegatecall 和 callcode
概念 低级别调用(Low Level Calls)包含: call():发出低级别调用,若发生异常则返回false callcode():发出低级别调用(类似代码注入),若发生异常则返回false delegatecall ():与callcode的区别在与msg指向不同 send():发送指定数量的wei到这个地址,若发生异常则返回false 低级别调用与普通函数调用(contract call)的区别: 普通调用中抛出异常事
二、call、callcode、delegatecall函数说明 call、callcode、delegatecall是以太坊智能合约编写语言Solidity提供的底层函数,用来与外部合约或者库进行交互
= 0){// 解析 call 地址INT i_callCode = *(INT*)(ul_entry + 1);DbgPrint("i_callCode = %p \n", i_callCode);ULONG64 ul_callJmp = ul_entry + i_callCode + 5;DbgPrint("ul_callJmp = %p \n", ul_callJmp);// 来到 call(PspReferenceCidTableEntry = 0){// 解析 call 地址INT i_callCode = *(INT*)(ul_entry + 1);DbgPrint("i_callCode = %p \n", i_callCode);ULONG64 ul_callJmp = ul_entry + i_callCode + 5;DbgPrint("ul_callJmp = %p \n", ul_callJmp);// 来到 call(PspReferenceCidTableEntry
/libhera.so --singletest callCode --singlenet "Byzantium" 显示结果: [2019-04-26 16:21:04.623418] [0x00007fc85b02fb00 Test Case "stEWASMTests": 100% Executing message in Hera importGlobals [0] callCode 186a0 0 20 20 1
不过也有一些例外:send,和底层的函数调用call, delegatecall,callcode,当发生异常时,这些函数返回false。 注意:在一个不存在的地址上调用底层的函数call,delegatecall,callcode 也会返回成功,所以我们在进行调用时,应该总是优先进行函数存在性检查。 底层操作如call,send,delegatecall或callcode除外,它们不会抛出异常,但它们会通过返回false来表示失败。 如果在使用new创建一个新合约时出现第3条的原因没有正常完成。
低级调用 一个合约可以通过call,delegatecall,staticcall或callcode等低级函数来进行调用。 4.谨慎使用低级函数:call,delegatecall,staticcall和callcode等低级函数提供了更大的灵活性,但也更容易出错。
账户模型将智能合约代码以对外完全隔离的方式在内部运行,实现了图灵完备的智能合约体系,本篇文章将从源码角度对其工作原理进行简要分析~ 合约调用 EVM提供了以下四个方法来实现合约的调用:EVM.Call、EVM.CallCode EVM.CallCode函数代码如下所示: // CallCode executes the contract associated with the addr with the given input in the sense that it executes the given address' // code with the caller as context. func (evm *EVM) CallCode It reverses the state in case of an execution error. // // DelegateCall differs from CallCode in the 在上面的调用分析过程中我们曾涉及到一个概念——"原生合约",当地址为原生合约时直接进入RunPrecompiledContract执行原生合约,无需通过解释器进行解释,我们对其简单介绍一下下: // CallCode
这次事件主要是利用了开发者对以太坊底层函数call、callcode、delegatecall的不当使用造成的。 call、callcode、delegatecall是以太坊智能合约编写语言Solidity提供的底层函数,用来与外部合约或者库进行交互。不当的使用会造成很严重的后果。
.callcode(…) returns (bool): 发起底层的callcode调用,失败时返回false。 不鼓励使用,未来可能会移除。
1] st.data = st.data[:len(st.data)-1] return } 内存 内存用于一些内存操作(MLOAD,MSTORE,MSTORE8)及合约调用的参数拷贝(CALL,CALLCODE Call A->B A,B的环境独立 CallCode、 和Call类似 区别在于storage位置不一样 DelegateCall、 和CallCode 参考 Call、CallCode、DelegateCall:https://ethereum.stackexchange.com/questions/3667/difference-between-call-callcode-and-delegatecall
SLOAD 常非纯粹性 0x55 SSTORE 常非纯粹性 0xf0 CREATE 常非纯粹性 0xff SELFDESTRUCT 常非纯粹性 0xf1 CALL 可能的非纯粹性调用类型 0xf2 CALLCODE CALLCODE 概况:使用此帐户的状态来执行其他帐户的代码。 参考: py-evm/evm/vm/logic/call.py: CallCode() 可能的非纯粹性理由: 从另一个帐户执行代码。 潜在攻击: 攻击者可能通过callcode来调用非纯粹性合约,并且读取或变异状态。
5,库(Libary) 库与合约类似,它们只需要在特定的地址部署一次,并且它们的代码可以通过 EVM 的 DELEGATECALL (Homestead 之前使用 CALLCODE 关键字)特性进行重用 msg.sender, msg.value 和 this 在调用中将保留它们的值, (在 Homestead 之前,因为使用了 CALLCODE,改变了 msg.sender 和 msg.value)。 与合约相比,库的限制: 没有状态变量 不能够继承或被继承 不能接收以太币 (将来有可能会解除这些限制) 5.1 库的调用保护 如果库的代码是通过 CALL 来执行,而不是 DELEGATECALL 或者 CALLCODE
MmIsAddressValid((PVOID64)ul_e8Addr)) { return 0; } INT ul_callCode = *(INT*)(ul_e8Addr + 1); ULONG64 ul_KiSetTimerEx = ul_e8Addr + ul_callCode + 5; return ul_KiSetTimerEx; } return MmIsAddressValid((PVOID64)ul_e8Addr)) { return 0; } INT ul_callCode = *(INT*)(ul_e8Addr + 1); ULONG64 ul_KiSetTimerEx = ul_e8Addr + ul_callCode + 5; return ul_KiSetTimerEx; } return MmIsAddressValid((PVOID64)ul_e8Addr)){return FALSE;}INT ul_callCode = *(INT*)(ul_e8Addr + 1);ULONG64