简单模拟使用Erc677完成token的转移以及两种业务的处理;
IERC677Receiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC677Receiver {
function onTokenTransfer(
address sender,
uint256 value,
bytes memory data
) external;
}
Erc677.sol
合约内部方法transferAndCall
实现token的转移,以及传递业务数据至to合约账户。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC677Receiver.sol";
abstract contract Erc677 {
event Transfer(
address indexed from,
address indexed to,
uint256 value,
bytes data
);
function transferAndCall(
address to,
uint256 value,
bytes memory data
) public returns (bool success) {
// 1. transfer
emit Transfer(msg.sender, to, value, data);
// 2. call
IERC677Receiver(to).onTokenTransfer(msg.sender, value, data);
}
///-----------------------测试--------------
function getSubId() public pure returns (bytes32) {
return keccak256("1");
}
function depositTest(
address to,
bytes32 subId,
uint256 amount
) public {
bytes4 sig = bytes4(keccak256("deposit(bytes32)"));
bytes memory data = abi.encodeWithSelector(sig, subId, amount);
transferAndCall(to, amount, data);
}
function oracleRequestTest(
address to,
uint256 amount,
bytes32 subId,
address callbackAddr,
uint256 nonce,
string calldata payload
) public {
bytes memory data = abi.encodeWithSignature("oracleRequest(bytes32,address,uint256,string)", subId,callbackAddr, nonce, payload);
transferAndCall(to, amount, data);
}
}
Oracle.sol
合约内部通过方法onTokenTransfer
接收业务数据,进行分类处理。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC677Receiver.sol";
contract Oracle is IERC677Receiver {
mapping(bytes32=>uint256) public balances;
mapping(bytes32=>string) public jobs;
event SubscriptionFunded(bytes32 indexed subId, address sender,uint256 oldBalance, uint256 newBalance);
// 处理token合约发来的call信息
function onTokenTransfer(
address sender,
uint256 value,
bytes calldata data
) public {
// call
bytes4 sig = bytes4(data[:4]);
if (sig == bytes4(keccak256("deposit(bytes32)"))) {
bytes32 subId = abi.decode(data[4:], (bytes32));
deposit(subId,value,sender);
}else if(sig== this.oracleRequest.selector){
(bytes32 jobId,address callbackAddress,uint256 nonce,string memory payload ) = abi.decode(data[4:], (bytes32,address,uint256,string));
oracleRequest(jobId,callbackAddress,nonce,payload,sender);
}else{
revert("Unsupport action");
}
}
function deposit(bytes32 subId, uint256 amount,address sender) public {
require(subId != bytes32(0), "Invalid subId");
require(amount != 0, "Invalid amount");
uint256 oldBalance=balances[subId];
uint256 newBalace = oldBalance + amount;
balances[subId] = newBalace;
emit SubscriptionFunded(subId,sender, oldBalance,newBalace);
}
event OracleRequest(
bytes32 indexed jobId,
address requester,
uint256 nonce,
address callbackAddr,
string data
);
function oracleRequest(
bytes32 jobId,
address callbackAddress,
uint256 nonce,
string memory data,
address sender
) public payable returns (bool) {
jobs[jobId]=data;
emit OracleRequest(jobId, sender,nonce, callbackAddress,data);
return true;
}
}