我在 Solidity 中编写了一份合同,并考虑了以下任务:
用户批准智能合约从他们的钱包中转移一定数量的代币。
智能合约使用此金额转移到作为参数给出的地址。但它也需要从这个数量中提取 1 个代币才能转移给合约的开发者。
如果一切成功,用户会收到“支付成功!” 信息。
第一步(批准)是使用 React 和 Web3 完成的:
const derc20contract = '0x36850b80ad73fe66216609B9796ed6ceae8BE29F';
const handleClick = async (e) => {
e.preventDefault();
const prtmp = await detectEthereumProvider();
// -------------------- Approve Part ------------------------------//
const web3 = new Web3(prtmp);
const erc20contract = new web3.eth.Contract(
erc20abi,
derc20token,
{ from: '0xFromAddress' }
);
await erc20contract.methods.approve(derc20contract, web3.utils.toHex(3e18)).send();
// ---------------------------------------------------------------//
const contract = new web3.eth.Contract(derc20abi, derc20contract);
const response = await contract.methods.send_usdt(
'0xToAddress',
web3.utils.toHex(3e18)
)
.call({ from: '0xFromAddress'});
console.log(response);
};
一旦批准成功,函数的第二部分就解决了。我部署的合约有一个名为send_usdt
. 通过这个功能,我的智能合约能够转移批准的金额。
/ SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
interface IERC20 {
function transfer(address _to, uint256 _value) external returns(bool);
function transferFrom(address _from, address _to, uint _amount) external returns (bool);
function allowance(address _owner, address _contract) external returns (uint256);
function balanceOf(address _buyer) external view returns (uint256);
function approve(address _contract, uint tokens) external returns (bool);
}
contract DPortalSubscription {
address private owner;
mapping(address => uint32) subscription_fees;
constructor()
{
owner = msg.sender;
}
function check_balance() external view returns (uint256)
{
// TestToken ( Plasma Bridge ) in Mumbai Network
IERC20 usdt = IERC20(address(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1));
uint256 balance = usdt.balanceOf(msg.sender);
return balance;
}
function check_sender_address() external view returns (address)
{
return msg.sender;
}
function check_allowance()external returns(uint256)
{
// TestToken ( Plasma Bridge ) in Mumbai Network
IERC20 usdt = IERC20(address(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1));
uint256 allowance = usdt.allowance(msg.sender, address(this));
return allowance;
}
function send_usdt(address _to, uint256 _amount) external returns (string memory)
{
// TestToken ( Plasma Bridge ) in Mumbai Network
IERC20 usdt = IERC20(address(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1));
require(_amount > 1, "Purchases must be higher than 1 usdt");
require(usdt.balanceOf(msg.sender) >= _amount, "The buyer doesn't have enough funds");
require(usdt.allowance(msg.sender, address(this)) >= _amount, "Permissions to transfer tokens denied");
require(usdt.transferFrom(msg.sender, _to, _amount-1) == true, "Couldn't transfer tokens to seller");
require(usdt.transferFrom(msg.sender, owner, 1) == true, "Couldn't transfer tokens to support");
return "Payment successful!";
}
}
一旦 React 中函数的第二部分解析完成,我就会收到“付款成功!”的确认信息。但是代币没有被转移。我在“From Wallet”、“To Wallet”和“Deploy Wallet”中保留了与以前相同的金额。
问题出在反应片段中。通过改变方法call
,sell
钱可以成功转移。
const response = await contract.methods.send_usdt
(
'0xToAddress',
web3.utils.toHex(3e18)
)
.call({ from: '0xFromAddress' });
改为:
const response = await contract.methods.send_usdt
(
'0xToAddress',
web3.utils.toHex(3e18),
{ from: '0xFromAddress' }
)
.send();
这有效,但提出了另一个问题。当我使用前面的call
方法时,函数返回“支付成功!” 并使用 sell 方法收到一个对象。
由于“付款成功”不是真的,我想知道当有人使用 call 方法与我的合约交互时是否可以抛出异常。
那可能吗?