一般的情况下,是可以类似于 chainlink 这类语言机,取到链下 http 的数据。
最近看到一个 https://www.apollox.finance/ 声称:链上存取款,链下交易引擎撮合交易
他在取款的时候,是通过前端发了一个 trasanction 到他的 https://bscscan.com/address/0x3e71726dbba7ce4e63b9ee58cf462184dc4c9737
看他这个 claim 的实现
function claim(bytes calldata message, bytes calldata signature) external notPaused {
address signer = source(message, signature);
require(signer == truthHolder, "only accept truthHolder signed message");
(uint256 id, address payable to, bool isBNB, address currency, uint256 amount, uint256 deadline) = abi.decode(message, (uint256, address, bool, address, uint256, uint256));
require(claimHistory[id] == 0, "already claimed");
require(isBNB || supportCurrency[currency], "currency not support");
require(block.timestamp < deadline, "already passed deadline");
claimHistory[id] = block.number;
_transfer(to, isBNB, currency, amount);
emit Claimed(id, to, isBNB, currency, amount, deadline);
}
例:一个 claim 的 tx: https://bscscan.com/tx/0x83f9f4cdda6d5ae3183a3239b4d6ddb4e0c980756817766aba415f0e7cc16836
貌似就是完全通过前端页面构造的取款金额,然后调用小狐狸签名,上链请求,合约没有做啥检查。。。 请教高手,他这种业务,大概是怎么实现的。。。
1
cxh116 2023-01-16 19:44:26 +08:00
return ECDSA.recover(hash, signature);
调用的库 https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol 合约里这行代码,走的是公私钥签名的,你拿不到私钥去签名消息,所以没办法. 估计私钥签名消息这一块肯定是 web2 服务端生成的,没做过这一块,靠猜的. 合约里的 receive 方法,这个是合约收到代币时自动触发,然后这合约自己触发了一个名为 ReceiveEther 的事件. 然后 web2 肯定会监听这个事件,记录每个地址的转帐多少钱,然后提款时先走 web2 接口验证你有没有转帐存款过,再调用 web3 签名取款. |
2
tangtj 2023-01-16 19:46:17 +08:00
message 里有金额, signature 是签名.
`signer == truthHolder ` 签名必须是由指定的账户签发的, 通过对 signature 进行校验确认 meaage 未被修改. 签名肯定是从服务器生成,由用户提交发起的. 这个场景你完全可以把提打款这部分理解为 第三方支付. |
3
cxh116 2023-01-16 19:50:02 +08:00
require(claimHistory[id] == 0, "already claimed");
这一行也限制了重放攻击,从这个 id 来看,肯定有 web2 数据记录是不是有存款过,和取款操作过. |
4
dreamramon OP 明白了,谢谢各位大神 ~~~
|
5
dreamramon OP @cxh116 #3
claimHistory[id] = block.number; 感觉他通过验证后就会把这个 claimHistory[id] 设为 那个区块号,但是没看到,他什么时候会设置成 0 。。。 不知道这里大概是一个什么样的原理? |
6
tangtj 2023-01-16 22:11:28 +08:00
@dreamramon 不存在的数据默认为 0
|