波场(Tron)USDT 合约授权(Approve)以及授权转账(TransferFrom)

发布时间 2023-09-25 11:38:54作者: lijingkun

授权(Approve)

private static async Task<string> ApproveAsync(string privateKey, string spenderAddress, decimal amount) {
	const string contractAddress = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";//合约地址

	var record = TronServiceExtension.GetRecord();
	var contractClientFactory = record.ServiceProvider.GetService<IContractClientFactory>();
	var contractClient = contractClientFactory?.CreateClient(ContractProtocol.TRC20);

	var account = new TronAccount(privateKey, TronNetwork.MainNet);
		
	const long feeAmount = 60 * 1000000L;//手续费上限
	return await contractClient.ApproveAsync(contractAddress, account, spenderAddress, amount, feeAmount);//广播交易
}

转账(TransferFrom)

private static async Task<string> TransferFromAsync(string privateKey, string fromAddress, string toAddress, decimal amount, string? memo) {
	const string contractAddress = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";//合约地址

	var record = TronServiceExtension.GetRecord();
	var contractClientFactory = record.ServiceProvider.GetService<IContractClientFactory>();
	var contractClient = contractClientFactory?.CreateClient(ContractProtocol.TRC20);

	var account = new TronAccount(privateKey, TronNetwork.MainNet);

	const long feeAmount = 60 * 1000000L;//手续费上限
	return await contractClient.TransferFromAsync(contractAddress, account, fromAddress, toAddress, amount, memo, feeAmount);//广播交易
}

聪明的人可能会联想到前段时间很热的0U转账的问题,这个操作其实就是省略掉了 Approve 的过程,直接调用 TransferFrom 由于转账金额是 0,不会发生实际转账操作,但是区块链的交易广播是成功的,所以导致转账记录被记录在账本上,然后小白盲目在交易记录里面复制到了陷阱地址,这个要是放在之前都不能讲,因为很多人导致这个问题转错账,受到不少损失。
但是现在波场基本上修复了这个问题,虽然没有从合约根本上解决,但这类的交易记录默认已经没有办法从区块浏览器和钱包里面复制了,虽然治标不治本。

调用

var privateKey1 = "";
var spenderAddress = "";

var result = await ApproveAsync(privateKey1, spenderAddress, 100);
Console.WriteLine(JsonConvert.SerializeObject(result));

var privateKey2 = "";
var fromAddress = "";
var toAddress = "";

//fromAddress 是 privateKey1 对应的地址,不是 spenderAddress
//privateKey2 是 spenderAddress 对应的私钥
var result = await TransferFromAsync(privateKey2, fromAddress, toAddress,100);
Console.WriteLine(JsonConvert.SerializeObject(result));

引入依赖库

PM> Install-Package Tron.Wallet.Net

配置主网信息已经 API Key

namespace Console1 {
    using Tron.Wallet.Net;

    public record TronRecord(IServiceProvider ServiceProvider, ITronClient TronClient, IOptions<TronNetOptions> Options);

    public static class TronServiceExtension {
        private static IServiceProvider AddTronNet() {
            IServiceCollection services = new ServiceCollection();
            services.AddTronNet(x => {
                x.Network = TronNetwork.MainNet;
                x.Channel = new GrpcChannelOption { Host = "grpc.trongrid.io", Port = 50051 };
                x.SolidityChannel = new GrpcChannelOption { Host = "grpc.trongrid.io", Port = 50052 };
                x.ApiKey = "80a8b20f-a917-43a9-a2f1-809fe6eec0d6";
            });
            services.AddLogging();
            return services.BuildServiceProvider();
        }

        public static TronRecord GetRecord() {
            var provider = AddTronNet();
            var client = provider.GetService<ITronClient>();
            var options = provider.GetService<IOptions<TronNetOptions>>();

            return new TronRecord(provider, client, options);
        }
    }
}