一个关于合约里面取链下数据的问题?

2023-01-16 19:25:56 +08:00
 dreamramon

一般的情况下,是可以类似于 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

貌似就是完全通过前端页面构造的取款金额,然后调用小狐狸签名,上链请求,合约没有做啥检查。。。 请教高手,他这种业务,大概是怎么实现的。。。

741 次点击
所在节点    问与答
6 条回复
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 签名取款.
tangtj
2023-01-16 19:46:17 +08:00
message 里有金额, signature 是签名.
`signer == truthHolder ` 签名必须是由指定的账户签发的, 通过对 signature 进行校验确认 meaage 未被修改.
签名肯定是从服务器生成,由用户提交发起的.
这个场景你完全可以把提打款这部分理解为 第三方支付.
cxh116
2023-01-16 19:50:02 +08:00
require(claimHistory[id] == 0, "already claimed");

这一行也限制了重放攻击,从这个 id 来看,肯定有 web2 数据记录是不是有存款过,和取款操作过.
dreamramon
2023-01-16 20:46:18 +08:00
明白了,谢谢各位大神 ~~~
dreamramon
2023-01-16 20:54:03 +08:00
@cxh116 #3
claimHistory[id] = block.number;

感觉他通过验证后就会把这个 claimHistory[id] 设为 那个区块号,但是没看到,他什么时候会设置成 0 。。。
不知道这里大概是一个什么样的原理?
tangtj
2023-01-16 22:11:28 +08:00
@dreamramon 不存在的数据默认为 0

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/909341

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX