最近有个新的需求
已经有一个代币合约如C,需要实现一个合约,在这个合约中调用代币合约C中的transfer函数,即转代币的函数。
要在一个合约中调用另一个合约,可用用以下三种方式调用。
- CALL:最常用调用,内置变量msg的值会被修改为调用者,执行环境为被调用者的运行环境。
- DELEGATECALL:调用后内置变量msg的值不会修改为调用者,但执行环境为调用者的运行环境。
- 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;
可以看到,这三种方式都并不符合我们的需求。
方法只有,先让用户调用代币合约C中的approve方法,再调用下面实现的合约中的depositToken方法。
pragma solidity ^0.4.25;
contract Deposit {
bool public stopped = false;
uint256 public totalDeposit=0;
uint256 minDepositValue;
address owner;
address cTokenAddr=0x01c2ce7bd1bc34eed8a99d0ea0abee305362c143;
uint256 minBlockGap;
mapping(address => mapping(string=>uint256)) depositRecords;
mapping(address=>mapping(string=>uint256)) withdrawRecords;
uint256 public account=0;
uint256 public blocknum ;
constructor(uint256 _minValue,uint256 _minBlockGap) public {
owner=msg.sender;
minDepositValue=_minValue;
minBlockGap=_minBlockGap;
}
event Withdraw(address indexed _from, string indexed _pk, uint indexed _value);
event DepositToken(address indexed _from,address indexed _to,uint256 indexed _value);
function depositToken(address _to,uint256 _value,string pk) public isRunning validAddress returns (bool sucess) {
require(_value>minDepositValue);
bytes4 transferFromMethodId = bytes4(keccak256("transferFrom(address,address,uint256)"));
if(cTokenAddr.call(transferFromMethodId,msg.sender,_to, _value)){
depositRecords[msg.sender][pk]+=_value;
totalDeposit+=_value;
emit DepositToken(msg.sender,_to,_value);
return true;
}
return false;
}
function setMinBlockGap(uint256 _blockGap) public onlyOwner {
minBlockGap=_blockGap;
}
function withdraw(uint256 _value,string _pk) public onlyOwner isRunning validAddress returns (bool sucess) {
require(depositRecords[msg.sender][_pk]>_value);
uint256 blockNumGap=getBlockNumGap(_pk);
if(blockNumGap<minBlockGap)
return false;
bytes4 transferMethodId = bytes4(keccak256("transfer(address,uint256)"));
if(cTokenAddr.call(transferMethodId,msg.sender, _value)){
depositRecords[msg.sender][_pk]-=_value;
withdrawRecords[msg.sender][_pk]=0;
totalDeposit-=_value;
emit Withdraw(msg.sender,_pk,_value);
return true;
}
return false;
}
function getDeposit(string pk) public view returns (uint256){
return depositRecords[msg.sender][pk];
}
function getDepositByAddr(address addr,string pk) public onlyOwner view returns(uint256){
return depositRecords[addr][pk];
}
function RequestWithdraw(string pk) public returns (bool){
getBlockNumGap(pk);
}
function getwithdrawRecords(string pk) public view returns (uint256){
return withdrawRecords[msg.sender][pk];
}
function getBlockNum() private view returns (uint256){
return block.number;
}
function getBlockNumGap(string pk) private returns (uint256){
uint256 number=getBlockNum();
if (withdrawRecords[msg.sender][pk]==0){
withdrawRecords[msg.sender][pk]=number;
return 0;
}else{
return number-withdrawRecords[msg.sender][pk];
}
}
function getTotalDeposit() public onlyOwner view returns (uint256){
return totalDeposit;
}
function stop(address _to,bool ifTransfer) public onlyOwner returns (bool sucess) {
stopped=true;
if(!ifTransfer){
return true;
}
bytes4 methodId = bytes4(keccak256("transfer(address,uint256)"));
if(cTokenAddr.call(methodId,_to,totalDeposit)){
totalDeposit=0;
return true;
}
return false;
}
function () payable public {
revert();
}
function start() public onlyOwner {
stopped = false;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
modifier isRunning {
require(!stopped);
_;
}
modifier validAddress {
require(address(0) != msg.sender);
_;
}
}
版权声明:本文为yujuan110原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。