shaneson.eth

Posted on Jul 02, 2022Read on Mirror.xyz

一个关于msg.sender的实战例子

背景

昨天帮忙朋友写了一个简单的合约,这个合约大概的需求是这样的:

他想用Cfx回收市面上的TokenA,用户调用redeem方法了之后,TokenA会自动转给合约,然后会按照一定的汇率转回Cfx给用户。合约上的TokenA收集完后,可以取回且销毁。

需求大概就是这样。因为Cfx需要先打进合约里,我把这个合约叫做ConvertPool/RedeemPool,

我周末大概用了3个小时,就写完了版本A,但是关键函数redeem会有一个比较致命的问题,这里记录一下,以免以后再有这类问题发生。

版本A

看下面的代码:

Redeem函数做了余额检查,然后把Ausd转给合约,然后再从合约转账cfx付款。但这里会有两个致命的问题:

  1. ausd.transferFrom 方法你不一定可以信任
  2. payable(msg.sender).transfer 也不一定可以信任,假如msg.sender是一个合约,那么就可以在callBack上发起重入攻击,锁在池子的全部cfx都可以被取走。

版本B

所以,最后需要一个Expect值去做check。转账了之后要做balance的check,确保余额是对得上的。

最后就是合约部署和测试了~

这次的收获就是,遇到msg.sender的逻辑,一定要先考虑:

假如msg.sender是合约发起的攻击,怎么办?

假如msg.sender是合约发起的攻击,怎么办?

假如msg.sender是合约发起的攻击,怎么办?