I am trying to send test USDT to a particular account in Java using the following code:
final Web3j web3 = createWeb3If(ethNetworkUrl);
final Credentials credentials = Credentials.create(privateKey);
final ERC20 usdtContract = ERC20.load(usdtContractAddress, web3, credentials, new TestGasProvider());
usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send();
The last statement results in the following exception:
java.lang.RuntimeException: Error processing transaction request: intrinsic gas too low
at org.web3j.tx.TransactionManager.processResponse(TransactionManager.java:176)
at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:81)
at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:128)
at org.web3j.tx.Contract.executeTransaction(Contract.java:367)
at org.web3j.tx.Contract.executeTransaction(Contract.java:350)
at org.web3j.tx.Contract.executeTransaction(Contract.java:344)
at org.web3j.tx.Contract.executeTransaction(Contract.java:339)
at org.web3j.tx.Contract.lambda$executeRemoteCallTransaction$3(Contract.java:410)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
at com.dpisarenko.minimalcryptoexchange.delegates.TransferUsdtToExchangeAccount.execute(TransferUsdtToExchangeAccount.java:57)
TestGasProvider is defined as:
public class TestGasProvider extends StaticGasProvider {
public static final BigInteger GAS_PRICE = BigInteger.valueOf(10L);
public static final BigInteger GAS_LIMIT = BigInteger.valueOf(1L);
public TestGasProvider() {
super(GAS_PRICE, GAS_LIMIT);
}
}
usdtContract
was deployed using this script, which calls deploy.js:
async function main() {
const USDT = await ethers.getContractFactory("USDT");
const usdt = await USDT.deploy(1000000000000000);
console.log("USDT contract deployed to:", usdt.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
This contract is running on a local testnet set up as described here.
What do I need to change in any of these components (testnet, contract, deploy scripts, Java code) in order to send any amount of USDT to a particular address (without any errors)?
Update 1: If I change TestGasProvider
to
public class TestGasProvider extends StaticGasProvider {
public static final BigInteger GAS_PRICE = BigInteger.valueOf(1L);
public static final BigInteger GAS_LIMIT = BigInteger.valueOf(1000000000L);
public TestGasProvider() {
super(GAS_PRICE, GAS_LIMIT);
}
}
I get another error:
java.lang.RuntimeException: Error processing transaction request: exceeds block gas limit
at org.web3j.tx.TransactionManager.processResponse(TransactionManager.java:176)
at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:81)
at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:128)
at org.web3j.tx.Contract.executeTransaction(Contract.java:367)
at org.web3j.tx.Contract.executeTransaction(Contract.java:350)
at org.web3j.tx.Contract.executeTransaction(Contract.java:344)
at org.web3j.tx.Contract.executeTransaction(Contract.java:339)
at org.web3j.tx.Contract.lambda$executeRemoteCallTransaction$3(Contract.java:410)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
at com.dpisarenko.minimalcryptoexchange.delegates.TransferUsdtToExchangeAccount.execute(TransferUsdtToExchangeAccount.java:57)
Update 1
I am looking to submit a set of code changes to the branch i16 of the minimal-crypto-exchange
project which passes the following test:
Step 1
Set up the environment as described here.
Step 2
Set a breakpoint on line usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send();
in TransferUsdtToExchangeAccount class:
Step 3
Start the process engine application in debug mode. Its Java main method is located here.
Wait until you see the message starting to acquire jobs
in the console output:
11:59:16.031 [JobExecutor[org.camunda.bpm.engine.spring.components.jobexecutor.SpringJobExecutor]] INFO org.camunda.bpm.engine.jobexecutor - ENGINE-14018 JobExecutor[org.camunda.bpm.engine.spring.components.jobexecutor.SpringJobExecutor] starting to acquire jobs
Step 4
Login with the credentials demo/demo
at http://localhost:8080.
After login you should see a page like this:
Step 5
Click on the tasklist link. You should see a page that looks like this:
Press the "Start process" link. Following screen will appear:
Click on Send USDT to the exchange account process
link. Following dialog box will appear:
Enter an arbitrary value into the "business key" field and press the "Start" button.
Step 6
After a couple of seconds, the breakpoint from step 2 will activate.
The problem will be solved if usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send()
is executed without errors.
Notes
- You are allowed to modify the amount in
usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send();
from10
to something else. - You can also modify the parameters of the Ethereum testnet specified in docker-compose.yml and genesis.json, as well as those of the USDT smart contract which is deployed using this script.
- Your solution must work in this controlled environment (i. e. no faucets must be used).
Update 2
I made following changes:
- The set-up tutorial now contains step 7 in which ETH is added to the exchange account.
- Now a new version of the ETH testnet is being used, major changes being that log output is more verbose and the gas price is set to 1 (see
--miner.gasprice 1
in entrypoint.sh). - Modified the code in TransferUsdtToExchangeAccount so that now USDT is transferred not from the exchange account (which has zero balance), but from the buffer account.
Now I am receiving the error
org.web3j.protocol.exceptions.TransactionException: Transaction 0x4bce379a2673c4564b2eb6080607b00d1a8ac232fbddf903f353f4eeda566cae
has failed with status: 0x0. Gas used: 32767.
Revert reason: 'ERC20: transfer amount exceeds allowance'.