Lets suppose here are smartcontract A and B. B is deployed already and has BuyService function. User need to call this function to get service with tokens. A has enough tokens(Erc20).
User send TX to A
A call B's BuyService
B receive tokens(erc20) in A and give service to User
Is this logic possible? If not, how can I make A? I dont want to change the code in B. B is very general. Pls correct me.
contract A {
ERC20 token = ERC20(0x...);
B b = B(0x...);
function helpMeBuyService() external {
token.approve(b, 1000);
b.BuyService(msg.sender);
}
}
Your code is correct
pragma solidity ^0.5.0;
interface B {
function BuyService(address receiver) external;
}
interface ERC20 {
function approve(address receiver, uint256 amout) external;
}
contract A {
ERC20 public token = ERC20(0x123);
B public b = B(0x123);
function helpMeBuyService() external {
token.approve(address(b), 1000);
b.BuyService(msg.sender);
}
}
Related
I'm trying to call a method from a contract that was instantiated from another contract. I use truffle console.
Here are the details: (I think you can gloss over the code, since this question is aimed at using truffle console, not fixing any bugs)
I have a contract called MyCoinSupply.sol:
pragma solidity ^0.8.0;
import "./MyCoin.sol";
contract MyCoinSupply is MyCoin("MyCoin", "MYC") // MyCoin is ERC20
{
constructor() public // gives 1000 tokens to the owner
{
_mint(msg.sender, 1000);
}
function getCoinbase() public returns (address) // for debugging purposes
{
return block.coinbase;
}
function _mintMinerReward() internal // gives 20 tokens to the miner
{
// _mint(block.coinbase, 20); // for some reason, block.coinbase is address 0
}
function _transfer(address from, address to, uint256 value) override internal
{
_mintMinerReward();
super._transfer(from, to, value);
}
}
I instantiate MyCoinSupply.sol within MyCoinDEX.sol:
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./MyCoinSupply.sol";
contract MyCoinDEX
{
IERC20 public token;
event Bought(uint256 amount);
event Sold(uint256 amount);
constructor() public
{
token = new MyCoinSupply();
}
function showSender() public view returns (address) // for debugging purposes
{
return (msg.sender);
}
function buy(uint256 amountTobuy) payable public // send ether and get tokens in exchange; 1 token == 1 ether
{
uint256 dexBalance = token.balanceOf(address(this));
require(amountTobuy > 0, "You need to send some ether");
require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
token.transfer(msg.sender, amountTobuy);
emit Bought(amountTobuy);
}
function sell(uint256 amount) public // send tokens to get ether back
{
require(amount > 0, "You need to sell at least some tokens");
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
}
Here's my migration for deploying contracts:
const MyCoinSupply = artifacts.require("MyCoinSupply");
const MyCoinDEX = artifacts.require("MyCoinDEX");
module.exports = function(deployer) {
deployer.deploy(MyCoinSupply);
deployer.deploy(MyCoinDEX);
};
Here's my problem:
When I try to call functions that belong to MyCoinDEX, all works well:
truffle(development)> let instance = await MyCoinDEX.deployed()
undefined
truffle(development)> instance.buy(1)
All is good here.
However, when I try the following I get an error:
truffle(development)> instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
evalmachine.<anonymous>:0
instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
^
Uncaught TypeError: instance.token.balanceOf is not a function
I Googled this error (I read this solution and this solution), but I didn't really stumble upon a solution. Can someone tell me how can I call token's methods from MyCoinDEX?
Thank you in advance!
When using solidity, I have a doubt when I need to call a function which was created in a different contract. I know 2 ways of doing it, and I don't understand what is more recommendable and why. These are the ways I know:
Method 1:
contract A {
function foo() external {
return true;
}
}
contract B is A {
foo();
}
Method 2:
contract A {
function foo() external {
return true;
}
}
contract B {
function callFoo() external {
A a = A(addressA);
return a.foo();
}
}
Could anyone tell me the differences, and when it is more convenient wo user wither Method 1 or Method 2?
Thank you!!
Method 1 is used when you're calling a contract that is deployed on the same address. It can be either a parent of your Contract B or a library that your contract has imported.
Since the foo method is external, you'd need to call it using this.foo();.
An external function f cannot be called internally (i.e. f() does not work, but this.f() works).
Source: Solidity docs
If it were public, you could call it internally, just using foo().
Method 2 is used when you're calling a contract that is deployed on a different address.
Your Contract B than doesn't have to redefine the Contract A, and can only define the interface:
// this is just an interface of an external contract
interface A {
function foo() external returns (bool);
}
// this is your contract
contract B {
function callFoo() external returns (bool) {
A a = A(addressA);
return a.foo();
}
}
I'm totally new to programming and I'm trying to code a Smart Contract that can receive funds and transfer them to other addresses through a function.
In my code I have a modifier that defines an owner that can call the withdraw/transfer function. I have defined 3 address variables, where the function transfers ETH to. Luckily it works as I want it to.
pragma solidity ^0.7.0;
contract SubscriptionPayment {
// address variable defining the owner
address public owner = msg.sender
;
// modifier that restricts access to the owner of contract
modifier onlyOwner{
require(msg.sender == owner);
_;
}
// contract is able to handle ETH
receive() external payable{
}
// function to withdraw restricted to owner
function withdraw(uint _value) external onlyOwner {
msg.sender.transfer(_value)
;
}
// define address variables
address payable public account1Address = 0xF6D461F87BBce30C9D03Ff7a8602156f006E2367 ;
address payable public account2Address = 0xb6a76127EDf7E0B7dfcEd9aDE73Fa8780eC26592 ;
address payable public account3Address = 0x722b95CA56b1C884f574BAE4832f053197Ca3F58 ;
// function to pay all subscriptions
function paySubscriptions() external onlyOwner {
account1Address.transfer(1000000000000000000);
account2Address.transfer(1000000000000000000);
account3Address.transfer(2000000000000000000);
}
My question concerns the paySubscriptions function. Is there any way to execute the transfers to these 3 addresses individually and sequentially? Of course I could just make 3 separate functions to transfer ETH to each of these addresses but that would give me 3 separate functions to call.
Is it possible to code that when one function is called, another one is called from within the contract and when this function is called, another one is called from within the contract? If so, I could code one function1 that can be called external and the other 2 functions are called from within the contract after function1 has been called/executed.
For a better understanding of your task, write how you would implement it if smart contracts could be written in Java or another language
You cold do something as follows:
Define an array of addresses and the amounts that they need transferring:
mapping (address => uint) public balances;
address payable [] public subscribers;
Then loop that mapping making payments for each such as:
function paySubscribers() public{
for (uint i=0; i<subscribers.length; i++) {
address payable currAddress = subscribers[i];
currAddress.transfer(balances[currAddress]);
}
}
I would suggest you read this article for a better understanding and more practice.
Looping in solidity
From the article:
In solidity, mapping is very useful to store token value of an
address. We have seen it in many contracts and they are normally
defined this way:
is this what you want?
function paySubscription(address receiverAddress, uint256 amount) external onlyOwner {
receiverAddress.transfer(amount);
}
function payAllSubs(address[] memory receivers, uint256[] amounts) external onlyOwner {
for (uint i=0; i<receivers.length; i++) {
address currAddress = receivers[i];
uint256 amt = amounts[i]
this.paySubscription(currAddress, amt);
}
}
I am using the openzeppelin for creating the ICO contract. I am concerned about the MinterRole here. After I develop Token contract, I added the sale contract as a minter using "addMinter" function.
Question
After the sale is over
I do not see a way to remove the contract address as a minter. I see that "renounceMinter" will remove only the person's who is calling this method.
I understand even If I remove (or) not remove the contract address as a minter at that point (i.e., after the sale is over) the Sale contract will b defined in such a way that it will not work at all. is it safe even if we leave the contract address in the minter list ?
Why openzeppelin has designed the "MinterRole" contract with the "renounceMinter" function that can remove only the person who is calling that contract but the function "addMinter" can do this for others also ?
Code
SampleCrowdsale
contract SampleCrowdsale is FinalizableCrowdsale, MintedCrowdsale
MintedCrowdsale
contract MintedCrowdsale is Crowdsale {
constructor() internal {}
function _deliverTokens(
address beneficiary,
uint256 tokenAmount
)
internal
{
// Potentially dangerous assumption about the type of the token.
require(
ERC20Mintable(address(token())).mint(beneficiary, tokenAmount));
}
}
ERC20Mintable
contract ERC20Mintable is ERC20, MinterRole
MinterRole
pragma solidity ^0.4.24;
import "../Roles.sol";
contract MinterRole {
using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private minters;
constructor() internal {
_addMinter(msg.sender);
}
modifier onlyMinter() {
require(isMinter(msg.sender));
_;
}
function isMinter(address account) public view returns (bool) {
return minters.has(account);
}
function addMinter(address account) public onlyMinter {
_addMinter(account);
}
function renounceMinter() public {
_removeMinter(msg.sender);
}
function _addMinter(address account) internal {
minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
minters.remove(account);
emit MinterRemoved(account);
}
}
Need help with two related Solidity questions.
Question 1. Say, I have a contract calling another one:
contract B {
function f1() {
...
}
}
contract A {
B b;
function f() {
b.f1();
}
}
Will msg.sender for f1 be same as for f()? Of will it be an address of a contract A?
Question 2.
Say, I have contracts A and B.
I want to have
contract A {
B b;
A(address addr) {
b = B(addr);
}
}
In other language, I would use B b = null; in declaration, to avoid double initialization, but it does not work in Solidity. So how do I declare a member variable and then initialize it by address?
Will msg.sender for f1 be same as for f()? Of will it be an address of
a contract A?
msg.sender will be the address of contract A. If you want to reference the original caller, use tx.origin.
So how do I declare a member variable and then initialize it by
address?
You don't need to worry about initialization when you declare the member variable. All variables in Solidity have default values. You can follow something like this:
contract B {
address sender;
function B(address addr) {
sender = addr;
}
}
contract A {
B b;
function A(){
b = B(msg.sender);
}
}