V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
dreamramon
V2EX  ›  问与答

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

  •  
  •   dreamramon · 65 天前 · 403 次点击
    这是一个创建于 65 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    这一行也限制了重放攻击,从这个 id 来看,肯定有 web2 数据记录是不是有存款过,和取款操作过.
    dreamramon
        4
    dreamramon  
    OP
       65 天前
    明白了,谢谢各位大神 ~~~
    dreamramon
        5
    dreamramon  
    OP
       65 天前
    @cxh116 #3
    claimHistory[id] = block.number;

    感觉他通过验证后就会把这个 claimHistory[id] 设为 那个区块号,但是没看到,他什么时候会设置成 0 。。。
    不知道这里大概是一个什么样的原理?
    tangtj
        6
    tangtj  
       65 天前
    @dreamramon 不存在的数据默认为 0
    关于   ·   帮助文档   ·   博客   ·   nftychat   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   951 人在线   最高记录 5556   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 21:23 · PVG 05:23 · LAX 14:23 · JFK 17:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.