主页 > 苹果版imtoken图标 > 智能合约开发及调用过程注意事项
智能合约开发及调用过程注意事项
智能合约功能:
1 合约一经部署,不可修改。
2 已建立的合约规则在合约被调用时触发,执行过程为原子执行(All or Nothing)
3 以太坊中的合约是公开可见的,启动合约的交易也是透明存储
solidity编写的合约在线编译URL:
以太坊账户分为:
外部账户,由账户私钥控制
合约账户,通过CREATE或CREATE2(主要用于状态通道,链下执行未部署的合约)
交易类型:
合约创建、触发合约交易、转账交易。
在一笔交易中,交易执行过程中的计算和存储成本是通过gas来评估的。
交易发起者通过指定gasLimit来限制gas成本。
合约方法执行
只能执行显式合约方法。
执行一个未定义的合约方法来触发fallback()external{}回调函数
向合约地址发送eth,触发receive()external pay{}回调函数。
合约中确定的业务规则,当给定相同的输入时,将始终执行相同的业务逻辑并产生相同的输出。
EVM
组合成可以在EVM中执行的字节码,通过EVM遍历字节码来改变状态。
堆栈宽度 256
操作码十六进制表示的范围是:00-ff,总共可以有256个不同的关键字
字节码网址:
通过字节码反编译反编译合约代码的研究是下一个研究热点
具体功能
tx.origin:当前交易Signer,在交易执行过程中不会改变
msg.sender:事务的直接调用者,在事务执行过程中可能会发生变化(调用)
合约交易注意事项
1 谁是事务中当前事务的发起者
调用合约会改变被调用者的msg.sender,可以确定实时交易调用者身份。但是,tx.origin 标识了交易的签名者,执行过程不会改变。因此,tx.origin 在执行过程中无法确定交易发起者的身份。 [中间合同攻击]
2 检查交易执行过程中是否超过gas(roo)
在事务中执行循环时,指定最大循环数
3 交易执行过程执行其他合约的调用
call、delegatecall、send等调用在root时不会返回异常,只会返回bool,所以做出必须调用的判断[require, if… else,assert]
transfer 在调用失败后返回异常。
并且在发送和转移调用时,只会向调用者发送2300 gas,以避免重入攻击
call和delegatecall会发送当前所有剩余gas,存在高gas成本风险
4 当前合约依赖于其他合约时
一旦依赖合约被销毁,依赖它的合约的数据状态就无法修改。因此,在依赖其他合约时,请确保自己所依赖的合约不能被销毁,并且没有selfdestruct关键字。
或者,通过library关键字调用合约库,库合约中的方法不会占用存储空间,所有存储都在自己的合约上。
5 DoS 的潜在风险
合约所有者身份变更->复杂的授权机制【所有者判断、多重签名验证、前置条件判断】
合约中有一个循环依赖于一个动态数组,而当前数组很大——“指定最大循环数
依赖于带有selfdestruct-"的外部合约,而是使用库合约,所有数据都存储在本地
外部调用的合约roo或通过代理合约改变实现合约
6 依赖以太判断的合约无法保证安全
自毁合约将执行执行。合约余额的退款将退回到指定账户。
7 交易的执行需要矿工排序,pre-runners存在高gasprice风险。
8 业务逻辑执行顺序不正确时,存在重入攻击风险。
为了保证安全,执行cheap-effects-interfacts的执行逻辑:
check:前置条件的判断,验证所有输入数据和当前状态
效果:更新本地状态,假设事务执行成功
interfacts:执行合约交互,触发其他合约的业务逻辑
合约部署前,通过合约验证工具进行检查:
预言机合约
合约无法直接获取外部数据,所以通过预言机引入合约获取链下数据
预言机合约验证链下数据并将其存储以供其他合约调用。
合约更新
通过代理合约更新合约
合约更新时,旧合约地址的数据无法迁移以太坊私链查询交易,或代理合约分为存储合约和逻辑合约
代工厂
通过合约 com = new contract(); return address(con) 实例化一个新合约以太坊私链查询交易,新实例化的合约都有相同的合约代码。
合约工厂允许通过实例化合约来部署具有相同代码的合约账户。
合约攻击练习