Solidity: contract calling another contract and addresses are different, why? - ethereum

I have a wrapper contract that instantiates and calls another contract, and my test cases say the owners (msg.sender)s don't match. Why?
contract A
pragma solidity ^0.4.4;
contract A {
address public owner;
function A() {
owner = msg.sender;
}
function createB(string name) {
return new B(msg.sender, name);
}
}
contract B
pragma solidity ^0.4.4;
contract B {
address public owner;
string public name;
function B(address _owner, string _name) {
owner = _owner;
name = _name;
}
}
test case
pragma solidity ^0.4.0;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/B.sol";
contract TestB {
B testB;
A testA;
function beforeEach() {
A = A(DeployedAddresses.A());
B = testA.createB("test");
}
function testOwnerIsSet() {
Assert.equal(address(A), address(B), "Owner's address does not match");
}
}
Test Results
1) TestB testOwnerIsSet:
Error: Owner's address does not match
at /Users/xxx/.config/yarn/global/node_modules/truffle/build/cli.bundled.js:214233:17
at Array.forEach (native)
at processResult (/Users/xxx/.config/yarn/global/node_modules/truffle/build/cli.bundled.js:214231:19)
at process._tickCallback (internal/process/next_tick.js:109:7)
EDIT
I have added the address public owner to contract A. And made owner public in contract B.
And now my TestB contract looks like this:
pragma solidity ^0.4.0;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/B.sol";
contract TestB {
B testB;
A testA;
function beforeEach() {
A = A(DeployedAddresses.A());
B = testA.createB("test");
}
function testOwnerIsSet() {
address aOwner = A.owner();
address bOwner = B.owner();
Assert.equal(aOwner, bOwner, "Owner's address does not match");
}
}

Based on what you have shown I am assuming you are using truffle? And to be honest I am surprised that this compiles.
When you call,
B = testA.createB("test");
you are calling it from TestB. msg.sender will be the address of TestB.
function createB(string name) {
return new B(msg.sender, name); // msg.sender = TestB instance address
}
This may be helpful to achieve what you are attempting.

Related

Error: Returned error: VM Exception while processing transaction: revert only owner can call this function

I'm trying to test this contract using "truffle test" but it show the following error:
Error: Returned error: VM Exception while processing transaction: revert only owner can call this function - - Reason given: Only owner can call this function.
Gaming.sol
pragma solidity ^0.5.0;
contract Gaming {
/* Our Online gaming contract */
address public owner;
bool public online;
struct Player {
uint wins;
uint losses;
}
mapping (address => Player) public players;
constructor() public payable {
owner = msg.sender;
online = true;
}
modifier isOwner() {
require(msg.sender == owner, "Only owner can call this function");
_;
}
}
TestGaming.sol
pragma solidity ^0.5.0;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Gaming.sol";
contract TestGaming {
uint public initialBalance = 10 ether;
Gaming gaming;
address owner;
function beforeAll() public {
gaming = Gaming(DeployedAddresses.Gaming());
owner = gaming.owner();
}
function testWithdrawFunds() public {
uint ownerBalanceBefore = owner.balance;
gaming.withdrawFunds();
uint ownerBalanceAfter = owner.balance;
Assert.equal (initialBalance, ownerBalanceAfter - ownerBalanceBefore, "The owner's balance should have increased by 10 ether");
}
Error
Error: Returned error: VM Exception while processing transaction: revert only owner can call this function - - Reason given: Only owner can call this function.
You may deployed the Contract with other account and test it with another accounts..
please do add your test script

Trouble calling contract functions from another contract

I have a roulette smart contract, that uses another smart contract to provide it with random numbers. The issue i'm having is during compilation, i get the error:
TypeError: Type contract IRandomNumberGenerator is not implicitly convertible to expected type address.
project:/contracts/Roulette.sol:34:29:
randomNumberGenerator = IRandomNumberGenerator(randomNumberGenerator);
I'm not exactly sure where i'm going wrong, i've seen this code used in other contracts. Here is my full code, any help would be much appreciated.
// SPDX-License-Identifier: UNLICENSED"
pragma solidity ^0.8.7;
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import "#openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "./IRandomNumberGenerator.sol";
contract Roulette is Ownable {
using SafeERC20 for IERC20;
IERC20 public gameToken;
uint256[100] internal randomNumbers;
IRandomNumberGenerator internal randomNumberGenerator;
// ensure caller is the random number generator contract
modifier onlyRandomGenerator() {
require(msg.sender == address(randomNumberGenerator), "Only random generator");
_;
}
constructor(address tokenAddress) {
gameToken = IERC20(tokenAddress);
}
function setRandomNumberGenerator(address randomNumberGenerator) external onlyOwner {
randomNumberGenerator = IRandomNumberGenerator(randomNumberGenerator);
}
function getRandomNumber() internal onlyOwner returns (uint) {
uint result = randomNumbers[randomNumbers.length-1];
delete randomNumbers[randomNumbers.length-1];
return result;
}
function numberGenerated(uint randomNumber) external onlyRandomGenerator {
randomNumbers = expand(randomNumber);
}
// generate 100 random numbers from the random number seed
function expand(uint256 randomValue) public pure returns (uint256[] memory expandedValues) {
expandedValues = new uint256[](100);
for (uint256 i = 0; i < 100; i++) {
expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i)));
}
return expandedValues;
// TODO - ensure random numbers are roulette numbers
}
}
// SPDX-License-Identifier: UNLICENSED"
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "./IRoulette.sol";
contract RandomNumberGenerator is VRFConsumerBase {
address public roulette;
bytes32 internal keyHash;
uint256 internal fee;
uint256 internal randomResult;
// modifier to check if caller of owner is the admin
modifier onlyRoulette() {
require(msg.sender == roulette, "Caller to function is not the roulette contract");
_;
}
constructor(address _roulette)
VRFConsumerBase(
0xa555fC018435bef5A13C6c6870a9d4C11DEC329C, // VRF Coordinator
0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06 // LINK Token
)
{
keyHash = 0xcaf3c3727e033261d383b315559476f48034c13b18f8cafed4d871abe5049186;
fee = 0.1 * 10 ** 18;
roulette = _roulette;
}
function getRandomNumber() public onlyRoulette returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
return requestRandomness(keyHash, fee);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
randomResult = randomness;
IRoulette(roulette).numberGenerated(randomResult);
}
}
Found out the issue was having the same name for both the parameter and the variable.
Updated the function to:
function setRandomNumberGenerator(address _randomNumberGenerator) external onlyOwner {
randomNumberGenerator = IRandomNumberGenerator(_randomNumberGenerator);
}

How to declare constants in Solidity

I am really new to Solidity and smart contracts and would really appreciate some help. I am following a tutorial and this is the exact code they use. But when I compile the code I get this error:
ParserError: Expected primary expression.
address public constant approver = ;
pragma solidity ^0.6.0;
contract ApprovalContract {
address public sender;
address public receiver;
address public constant approver = ;
function deposit(address _receiver) external payable {
require(msg.value > 0);
sender = msg.sender;
receiver = _receiver;
}
function viewApprover() external pure returns(address) {
return(approver);
}
function approve() external {
require(msg.sender == approver);
receiver.transfer(address(this).balance);
}
}
The constant needs to be initialized
address public constant approver = YOURADDRESS;
There are 2 types of constant variables in Solidity:
Constants: a variable that is hardcoded in the smart contract and that you cannot change the value
Immutables: variables you can only define the value in the constructor and that cannot be updated afterwards
Here is an example:
uint256 public constant EXAMPLE_NUMBER = 123;
unit256 public immutable EXAMPLE_NUMBER_2;
constructor(uint256 _number) {
EXAMPLE_NUMBER_2 = _number;
}
You can read more about it here.

callling deployed contract xyz public payable function from deployed contract abc with hexdata in Solidity

In deployed contract with address abc I have:
function CallContract(address tosend,uint amount,bytes hexdata,uint zgas) public payable {
tosend.call.gas(zgas).value(amount)(hexdata);
}
In web3 I have
await AbcContract.methods
.CallContract(this.state.tosend,amounttowei,web3.utils.fromAscii(data),gas)
.send({
from:accounts[0]
});
In the deployed contract with address xyz I have:
uint public somevar;
uint public anothervar;
function DoSomething() public payable {
uint somevar = 1;
}
function DoSomethingAgain(uint justanumber) public payble {
uint anothervar = justanumber;
}
What am I doing wrong?
In etherscan I get
Although one or more Error Occurred [Out of gas] Contract Execution Completed

How to test a contract which is generated by another deployed contract?

Currently, I want to test a contract called B which is generated from another contract Registry by using truffle. For example:
Contract Registry
pragma solidity >=0.4.17;
import "./B.sol";
contract Registry is Owned {
function createContract(
address userAddress)
public
returns(
bool res
)
{
// create a contract B which the owner is the user.
B b = new B(userAddress);
return true;
}
Contract B
pragma solidity >=0.4.17;
contract B {
address private owner;
constructor (
address _owner
)
public
{
owner = _owner;
}
function logData(
bytes32 data,
uint timestamp
)
public
returns(bool res)
{
...
}
...
testing script B.js in truffle/test:
const Registry = artifacts.require('./Registry.sol');
const B = artifacts.require('./B.sol');
const truffleAssert = require('truffle-assertions');
const assert = require('assert');
contract('Registry', (accounts) => {
let registry;
let B;
beforeEach(async () => {
// create a reportSummary contract from registry contract.
registry = await Registry.deployed();
// How can I retrieve the contract B's instance?
});
Because I am a newbie in solidity, thus I cannot find any way to test the function logData or other functions in contract B which depends on the contract Registry. Is there any suitable way or should I change the contract designed? Thanks.
You can check my this answer it has example too about accessing the function from imported contract
Solidity: Can a Parent contract see data updates from a Child contract?
To access the function through web3, just use the instance of Registry contract and you can call the function of Contract B