最近报名参加了硅谷区块链举办的《智能合约开发课》第二期培训班,根据培训要求,不能透露课程的内容,但我会在steemit上记录我的成长过程。
根据最近学习的内容,我编了一个应用场景:
几个人合伙凑出几个ETH,发给代投方agent;代投方发放token后,按份额发给每个参与者
1)结构struct
这个需求里涉及了多个参与者,我们需要记录其钱包地址和参投的份额。Solidity支持struct结构类型,这点与C语言非常相似,建立一个参与者的结构后,可以记录每个参与者的地址和参投数量。
struct Participator {
address addr;
uint amount;
}
2)数组
Solidity支持定长数组和动态数组,这里我们的参投人数是不定的,所以用动态数组。
Participator []participators;
在动态数组中增加一个元素用push()函数。参投者向合约地址里支付ETH后,需要记录其地址和参加的份额。这里需要在addFund()函数中增加这样一行。
participators.push(Participator(msg.sender, msg.value));
3)安全考虑
涉及到转账操作时要特别注意,不能让无关人员执行这些函数,通常的做法是声明一个成员变量address owner
,然后在构造函数中记录合约的创建者owner。
构造函数的名称与合约名称一致,并且不带任何参数。
function CoinProxy() {
owner = msg.sender;
}
然后在各个函数中判断函数的调用者是否有权限执行转账操作,如果没有权限,中止函数的执行。
if(msg.sender != owner) {
revert();
}
4)异常处理及状态回滚
solidity在执行过程中如果遇到异常要保持原子操作的完整性,需要将各种状态恢复成调用前的状态,需要用到revert()函数。在比较早的solidity版本中都用throw(),现在统统用revert()。
在solidity中经常要进行这些类似的判断,如果都用if语句,则显得非常臃肿,可以把上面的if语句用require写成一行。
require(msg.sender == owner);
这种表达方式在solidity中大量存在,语法精练,语义清晰。
5)统计参投的总币数
for语法与C语言一样,没什么可讲的。
uint total = 0;
for(uint i = 0; i<participators.length; i++){
total += participators[i].amount;
}
6)发出token
收到代投方换回的token后,要发给每个参投方。这里我还不知道如何发放ERC-20代币,先假设发放balance里的ether吧。这里按份额发放即可。
for(i = 0; i<participators.length; i++){
participators[i].addr.transfer(this.balance * participators[i].amount / totalEthers);
}
主要的步骤就是这些,程序里还有一些问题没有考虑,没有考虑代投过程的起止时间,如果换回token后,仍有人追加资金,份额的计算是有问题的。这些细节留着以后再考虑。
完整的代码:
pragma solidity ^0.4.14;
contract CoinAgent {
// 与C语言类似,支持结构类型
struct Participator {
address addr;
uint amount;
}
//用remix中生成的第5个测试地址,收集到的ETH发给他
address agent = 0xdd870fa1b7c4700f2bd7f44238821c26f7392148;
// 参投方,动态数组
Participator []participators;
address owner;
function CoinAgent() {
owner = msg.sender;
}
// 每个参投方调用这个函数参投
function addFund() payable returns(uint) {
participators.push(Participator(msg.sender, msg.value));
return this.balance;
}
// 送给代投方
function sendToAgent() {
if(msg.sender != owner) {
revert();
}
agent.transfer(this.balance);
}
// 把tokens按照参加份额发给每个参投人
// 当前还不知道如何发ERC-20代币,先发ETH
function sendTokens() {
require(msg.sender == owner);
uint total = 0;
for(uint i = 0; i<participators.length; i++){
total += participators[i].amount;
}
// 前面定义的i变量在整个函数中都可以访问
for(i = 0; i<participators.length; i++){
participators[i].addr.transfer(this.balance * participators[i].amount / total);
}
}
}
本文由币乎(bihu.com)内容支持计划奖励