作者:GoPlus Security
近期,一些使用 Vyper 0.2.15 版本编写的稳定池(alETH/msETH/pETH)遭受了重入攻击。这是由于该版本编译器实现错误导致的重入锁故障问题。此漏洞导致了约5000万美金的损失。本文将分析该漏洞的根本原因和攻击原理。同时,将提供优化建议以防止类似事件再次发生。
漏洞根源来自于编译器对@nonreentrant(<str>)修饰器语义的错误实现。
@nonreentrant(<str>)是用于限制函数的重入,其语义则类似于多线程中的互斥锁:
单函数修饰:当一个函数被该修饰器修饰,它的多个调用无法同时执行。
多函数修饰:当多个函数都使用该修饰器,且重入限制键相同(字符串值相同),它们的多个调用仍然无法同时执行。
一个正确的实现是,对每个重入限制键设置一个布尔值,0代表有一个函数在执行,1代表没有函数执行。多个被该键限制的函数根据该变量来进行同步(获得键-1,释放键+1,尝试获得键需检查值是否为1)。
在Vyper编译器0.2.15版本及之前,对于该语义的实现是错误的。错误代码如下所示。