I'm attempting to fork Safemoon (or really NotSafeMoon), and use it as a vehicle to learn smart contract development. (I've got a substantial amount of what you might call "Web 2.0" dev experience).
So say I have something like so in my constructor:
constructor () {
_rOwned[_msgSender()] = _rTotal;
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E); // binance PANCAKE V2
uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this), _uniswapV2Router.WETH());
When I run my tests with npx hardhat test
I get the following failure:
Compilation finished successfully
TestToken contract
Deployment
1) "before each" hook for "Has the right name"
0 passing (807ms)
1 failing
1) TestToken contract
"before each" hook for "Has the right name":
Error: Transaction reverted: function call to a non-contract account
Now, this does make perfect sense, after all I am attempting to call the Pancakeswap v2 router contract. How do I get around this limitation? Is there a way to inject the contract address for the router as an environment variable perhaps? Is there a mock constructor for the UniswapRouter I can be using? Generally, how is this sort of thing done in a way that remains testable (and how is it therefore tested) with smart contract development?
A hardhat test deploys the contracts to the hardhat local network (by default). This local network only has few pre-funded and unlocked accounts, but there are no smart contracts deployed. Including the PancakeSwap v2 Router (0x10ED43...).
Instead of deploying and configuring local copy of the router contract, as well as all of its dependencies, you can create a new hardhat network forked from the production BSC.
https://hardhat.org/guides/mainnet-forking.html
This will run a local network with the Router contract available, but your actions will only effect the local network (not the mainnet).