这篇文章我觉得很有含金量,哈哈。
最近打的NFT项目,有一些是需要从前端获取签名的。这个时候,市面上大部分的Mint工具都未必能过得了这一关。
我在网上搜索了很多的资料,目前关于提前获取签名的教程几乎没有。科学家们的分享基本上都止步于合约mint、16进制mint等常规的mint方法,这些在我之前的文章里面也有提到。目前基本上来说超过半数的人都会这些mint方法,统称为非网页端mint方法吧。
当一个NFT项目限制了必须要获取前端服务器签名才能mint的时候,大部分人就只能干瞪眼或者老老实实去前端mint了(当然前端大概率是抢不到的)。
首先说下限制前端服务器签名才能mint的原理。这里以ApeDog为例。在合约的mint方法中,加了一个限制条件。
require(isAuthorized(sig,digest),"CONTRACT_MINT_NOT_ALLOWED");
就是说,每个钱包都需要提供一个签名才能调用mint的方法。这个签名需要从前端网页获取,是由项目方的钱包进行签署的。用户拿着签名去调用合约的mint方法时,合约就会根据签名反推出签名的内容,如果得到的内容(一般就是调用者的地址)是正确的,那么就允许用户进行mint。理论上,签名应该是对调用者的钱包进行签名,这样就不会出现所有人都共用一个签名的伪签名方式。之前有许多项目出现过类似的BUG,后来的人拿到前面人的签名就可以跳过前端直接合约mint。ApeDog这个项目,不光是对调用者的钱包进行了签名,还为每个签名给定了一个有效时间,过了这个有效时间签名就会作废。这个设置挡住了许多提前获取签名的人。
那么前端是如何拿到签名的呢?我们在前端进行mint的时候,一般先连接小狐狸钱包,然后点击mint的按钮,就会跳出小狐狸窗口了,在小狐狸窗口中提交交易即可进行mint。其实在跳出小狐狸窗口的时候,我们看data里面的内容,就已经包含了我们所需要的签名信息了。这是最正规的获取签名的渠道。如果我们想要通过科学家的方式来获取签名的话,首先需要了解前端获取签名的过程。
当我们点击mint按钮的时候,在前端网页就会触发一个event。这个event就会通过一个接口把我们的钱包地址等信息发给后台,后台在收到这些信息后,会调用项目方的钱包对这些信息进行签名,然后返回给前端。这个就是前端获取签名的基本流程。
所以,如果我们不想老老实实的点击mint按钮去获得签名的话,就需要我们自己直接去调用这个接口来和后台进行互动。
调用接口的方式很简单,一般就是两种方法,GET和POST。获取签名的话一般会用POST。调用POST方法的时候,需要输入两个参数,一个是目标url,一个是headers。url就是接口的地址,headers就是我们需要代入的参数。
那么如何获得接口的url地址呢?两种方法,第一个,在前端页面的上通过f12打开开发者模式,在network选项卡中抓包。点击mint按钮后,找到网页对应发送的post请求,在请求中就可以得到我们需要的url了,顺便还能看到我们的headers中包含的参数,一举两得。这种方法的前提是网页要能打得开,一般情况下,比较火爆的项目在发售的时候,前端都会卡的根本没有机会点击mint按钮…
第二种方法的门槛就比较高了,那就是阅读网页的源代码。大部分的NFT项目的源代码都会暴露在网页上,通过开发者模式就可以查看到。通过f12进入开发者模式下,就可以看到网页的js文件。这些js文件可能也是经过了处理,一般可读性都很差…还是以ApeDog项目为例,因为迄今为止我只从它这找到了接口地址。
在apedog.wtf这个目录下只有一个js文件,所以找起来目标就比较明确了。有的项目目录下还有好多文件,找起来就不太好定位了。
点击打开js文件,搜索POST,会出来许多匹配结果。一个一个看一下,看到这里,就需要注意下了。后面跟着一个sigurl。推测这个sigurl就是接口地址。接着搜索sigurl。
这下就看到了,后面的这个url应该就是我们要找的接口url了。接着看,下面一行还有一个auth,这个一般需要写在headers里面,类似一个授权的东西。
接着搜索sigurl,看到这个部分。这里有两个参数,一个是sender,应该就是我们的钱包地址了,还有一个Authorization,就是需要我们刚才看到的auth的内容。那么,接下来我们就可以去调用POST方法了。
这里用python的request库。
import requests
url = 'https://1-0-0--wen-wl.rekttt.autocode.gg/'
auth = 'tok_prod_DxcW8FCKenfdpGDbGD8puUfjqmEYCpPTZ5DijpGLd1XHpzaep19jxyds6y6HLMQ1'
headers = {
'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36',
'Authorization': 'Bearer ' + auth,
'sender': 'wallet address'
}
res = requests.post(url,headers)
print(res.text)
填入我们扒出来的url、auth还有我们自己的钱包地址。运行结果如下:
{"signature":"0xf5d836dbeb2662e5066256456d8a2d05d6de926d28e4e70861cd90dbd755345710d83b290bce4dfd530042d2c32f8fc2d287a535fcf89187b008baf8e386e816","expireTime":1658179246}
看看这是啥,这就是我们需要得到的签名了。我们绕过了前端,直接通过接口的方式提前获取到了签名,拿着这个签名就可以去mint啦。这个方法需要我们能够从js文件中找到接口的地址,还需要弄清楚接口需要发送那些参数,比较考验我们的经验还有阅读代码的能力。不同的项目的代码都是不一样的,所以基本上每个项目都得重新修改获取签名的方式。对于普通玩家就非常不友好了。这里也非常佩服市面上的一些工具,能够自动获取签名,让用户赢在起跑线。不得不说,收费有收费的道理啊!