Bài viết
Chia sẻ kiến thức của bạn.
Solidity và ethers.js Tính toán các địa chỉ khác nhau từ cùng một chữ ký
Kịch bản này:
const { ethers } = require('ethers');
async function recoverSigner(address, nonce, deadline, v, r, s) {
const domain = {
name: "RandomReachDebug5Local",
version: "1",
chainId: 31337,
verifyingContract: "0x8464135c8F25Da09e49BC8782676a84730C318bC",
};
const types = {
RequestRandomNFT: [
{ name: 'minter', type: 'address' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' },
],
};
const value = {
minter: address,
nonce: nonce,
deadline: deadline,
};
// Get the digest of the message
const digest = ethers.utils._TypedDataEncoder.hash(domain, types, value);
const sig = {
r: r,
s: s,
v: v,
};
if (sig.v < 27) {
sig.v += 27;
}
const signer = ethers.utils.recoverAddress(digest, sig);
return signer;
}
const address = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266";
const nonce = "0";
const deadline = "1685162164";
const v = "28";
const r = "0xe0e4cc2f8b6bac3784f9feb3db4382291631d5f317d08a0b82305e5eb5ffc60a";
const s = "0x0416d521d12e26b8fc1f4bd566d5d67c5dffebe9564fe90db4f12c0a69b63d5e";
async function run() {
try {
const signer = await recoverSigner(address, nonce, deadline, v, r, s);
console.log(`The signer is: ${signer}`);
} catch (error) {
console.error(`Error in recovering signer: ${error}`);
}
}
run();
Produces this output: The signer is: 0x1AB26702A8068a247BD33a9555dfEf791d2BD68D
But this solidity contract:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
contract GetAddressFromSig is ERC721, EIP712 {
struct Request {
address minter;
uint256 nonce;
uint256 deadline;
}
bytes32 public constant REQUEST_TYPEHASH = keccak256("Request(address minter,uint256 nonce,uint256 deadline)");
// Initialize _DOMAIN_SEPARATOR directly with static values
bytes32 private immutable _DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes("RandomReachDebug5Local")), // static name
keccak256(bytes("1")), // static version
31337, // static chainId
0x8464135c8F25Da09e49BC8782676a84730C318bC // static verifyingContract
)
);
constructor(string memory name, string memory symbol) ERC721(name, symbol) EIP712(name, "1") {}
function domainSeparator() public view returns (bytes32) {
return _DOMAIN_SEPARATOR;
}
function recoverSigner(Request memory request, uint8 v, bytes32 r, bytes32 s) public view returns (address) {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
_DOMAIN_SEPARATOR,
keccak256(
abi.encode(
REQUEST_TYPEHASH,
request.minter,
request.nonce,
request.deadline
)
)
)
);
// ECDSA.recover returns the address that is associated with the public key
// that was used to sign the given data, in this case, the digest.
return ECDSA.recover(digest, v, r, s);
}
}
Deployed with this script in hardhat:
import { ethers } from "hardhat";
const hre = require("hardhat");
const dotenv = require("dotenv");
dotenv.config();
async function main() {
const GetAddressFromSig = await hre.ethers.getContractFactory("GetAddressFromSig");
const gasPrice = await GetAddressFromSig.signer.getGasPrice();
console.log(`Current gas price: ${gasPrice}`);
const estimatedGas = await GetAddressFromSig.signer.estimateGas(
GetAddressFromSig.getDeployTransaction("RANDOM NFT 5", "RNFT5"),
);
console.log(`Estimated gas: ${estimatedGas}`);
const deploymentPrice = gasPrice.mul(estimatedGas);
const deployerBalance = await GetAddressFromSig.signer.getBalance();
console.log(`Deployer balance: ${ethers.utils.formatEther(deployerBalance)}`);
console.log(`Deployment price: ${ethers.utils.formatEther(deploymentPrice)}`);
const getAddressFromSig = await GetAddressFromSig.deploy("RANDOM NFT 5", "RNFT5");
await getAddressFromSig.deployed();
console.log("GetAddressFromSig deployed to:", getAddressFromSig.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
And ran with these commands in the hardhat console:
const Token = await ethers.getContractFactory("GetAddressFromSig");
const token = await Token.attach("0x8464135c8F25Da09e49BC8782676a84730C318bC");
const request = { minter: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", nonce: ethers.BigNumber.from("0"), deadline: ethers.BigNumber.from("1685162164") };
const v = 28
const r = "0xe0e4cc2f8b6bac3784f9feb3db4382291631d5f317d08a0b82305e5eb5ffc60a";
const s = "0x0416d521d12e26b8fc1f4bd566d5d67c5dffebe9564fe90db4f12c0a69b63d5e";
const signer = await token.recoverSigner(request, v, r, s);
console.log(`The signer is: ${signer}`);
Cung cấp cho đầu ra này: người ký là: 0xEB7265F6625EAE66403A637C073E63CCF33B8CDC
Vậy tại sao javascript tính 0x1AB26702A8068A247BD33A9555DFEF791D2BD68D, trong khi trình biên dịch solidity của hardhat tính 0xEB7265F6625EAE66403A637C073E63CCF33B8CDC?
- Smart Contract
- Solidity
Câu trả lời
1Tôi thấy một sự không phù hợp. REQUEST_TYPEHASH
uses the type name Request
. Type name in JavaScript when defining type is RequestRandomNFT
.
Ngoài ra, bạn có thể thử mã thay thế này để đăng nhập vào JavaScript:
const value = {
minter: address,
nonce: nonce,
deadline: deadline,
};
const domainType = [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
];
const requestType = [
{ name: 'minter', type: 'address' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' },
];
const domainData = {
name: 'RandomReachDebug5Local',
version: '1',
chainId: 31337,
verifyingContract: '0x8464135c8F25Da09e49BC8782676a84730C318bC',
};
const dataToSign = JSON.stringify({
types: {
EIP712Domain: domainType,
Request: requestType,
},
domain: domainData,
primaryType: 'Request',
value,
});
const signature = await provider.send('eth_signTypedData_v4', [signerAddress, dataToSign]);
Bạn có biết câu trả lời không?
Hãy đăng nhập và chia sẻ nó.
Solidity is an object-oriented, high-level language for implementing smart contracts. It is a curly-bracket language designed to target the Ethereum Virtual Machine (EVM).
Kiếm phần của bạn từ 1000 Sui
Tích lũy điểm danh tiếng và nhận phần thưởng khi giúp cộng đồng Sui phát triển.
- My ERC721 contract successfully deploys, but I can't verify the contract's source code with hardhat21
- Solidity và ethers.js Tính toán các địa chỉ khác nhau từ cùng một chữ ký21
- không thể hiểu các vị trí là gì (uint256)22
- Làm thế nào để đảo ngược keccak256 trong độ rắn22
- Làm rõ về hoàn tiền gas và so sánh giữa “yêu cầu” và “hoàn lại” trong hợp đồng thông minh21