Using a state variable from another contract - solidity

How I can use a state variable which is in another contract(contract_a) in my contract(contract_b).
That variable is public. I just want to use some special variables not all data that are in contract_1.

First answer here, I wish it'll be helpful.
It looks like every variable of a contract has an implicit getter method, which at first I thought was a little unusual.
When you call this variable from another contract, you are calling its getter method.
So, instead of calling car.color, you've got to call car.color().
I'm still learning, so DYOR.

When you use the import statement in a contract you import all the functions and all the variables of the smart contract you are importing.
In your contractB you need to have an instance of the contractA (or its address) and then call through this instance the variable you want to access. E.g:
import "./ContractA.sol"
contract ContractB {
ContractA instanceOfA;
function callA() public {
instanceOfA.variableYouWantToAccess();
}
}
Note the parentheses () after the name of the variable you want to access, that is because Solidity, for all the varibles, specifies a getter function which is the function you call in order to access these varibles.

Related

Using "ERC20" and interfaces names as variable (in functions)

I'm having problems wrapping my head around ERC20 and interfaces passed as variables.
Examples:
function foo(ERC20 _project) external { //some code }
function fuu(IERC4626 _project) external { ERC20(_project.asset()) }
What does this exactly do and how do we use it?
Haven't been able to find any explanation next to: Using interface name as Variable type. A link to the explanation is also fine.
My guesses:
Example 1: we input an address type which simply refers to an ERC20 contract, which we can use then as:
Project project = _project;
project.withdraw();
If above is true, why don't we simply take in an address type in the function instead of "ERC20" type?
Example 2: Calls an ERC20 contract which implements the IERC4626 interface? If so, how is that checked? tbh I have no idea.

Calling function from already deployed contract in solidity?

I want to know how to call a function from already deployed contract in solidity. I tried below one but it's throwing error and require without imorting the deployed contract
contract B {
watch_addr = 0x1245689;
function register(string _text) {
watch_addr.call(bytes4(keccak256("register(string)")), _text);
}
}
Can any one please tell me the solution?
error:browser/delegate.sol:14:31: TypeError: Invalid type for argument in function call. Invalid implicit conversion from bytes4 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it.
watch_addr.call(bytes4(keccak256(abi.encode("register(string)"))));
In version 5.0 Solidity had some breaking changes:
The functions .call() ... now accept only a single bytes argument. Moreover, the argument is not padded. This was changed to make more explicit and clear how the arguments are concatenated. Change ... every .call(signature, a, b, c) to use .call(abi.encodeWithSignature(signature, a, b, c)) (the last one only works for value types). ... Even though it is not a breaking change, it is suggested that developers change x.call(bytes4(keccak256("f(uint256)"), a, b) to x.call(abi.encodeWithSignature("f(uint256)", a, b)).
So, the suggested way to call other contract is like this:
pragma solidity ^0.5.3;
contract test3 {
address watch_addr = address(0x1245689);
function register(string memory _text) public {
watch_addr.call(abi.encodeWithSignature("register(string)", _text));
}
}
Also note added memory keyword: you now need to specify data location for function parameters of complex types:
Explicit data location for all variables of struct, array or mapping types is now mandatory. This is also applied to function parameters and return variables.

How to access the event arguments passed to a ColdBox module?

I have a view in my ColdBox application that is calling a module handler within the view like this:
#runEvent( event="mymodule:home.index" )#
Now I want to pass arguments to the module, so I changed the call to this:
#runEvent( event="mymodule:home.index", eventArguments=moduleArgs )#
Though unfortunately I don't seem to have access to the passed arguments within the module's event handler. I've dumped rc and prc, but they only contain variables I've set in the main event handler and the event argument doesn't seem to provide a method to return the passed arguments. The documentation about module event executions unfortunately doesn't provide any information about this.
Also, I realized calling event.getCurrentModule() within the module returns an empty string. I would have expected the module's name.
So, how can I access the arguments passed to a module? Is runEvent() the right function for this? Did I miss a module config setting?
You can define arguments in your function like this
function index(event, rc, prc, isRender=false) {
writedump(arguments);
abort;
}
See the ColdBox runEvent() documentation.
The ColdBox documentation explains how to pass additional arguments to your function. So e.g. calling
#runEvent( event="mymodule:home.index", eventArguments={foo="bar"} )#
the foo variable can be accessed via the arguments scope:
function index(event, rc, prc) {
writedump(arguments.foo); // Dumps "bar"
}

How to make function wait to return after getResult from SQL Statement is available?

I'm just trying to make a simple function that will return all the data from my SQLITE database as an array. But it looks like when my function is returning the array, the SQL statement is actually still executing... so it's empty... Does anyone have a suggestion? Or am I just going about this whole thing wrong.
I know I could just have the event listener functions outside this function, and they could then set the data. But i'm trying to make a AS3 Class that holds all my SQL functions, and It would be nice to have everything for this particular function just in one function, so it can return an array to me.
public function getFavsGamesArray():Array
{
getFavsArraySql.addEventListener(SQLEvent.RESULT, res);
getFavsArraySql.addEventListener(SQLErrorEvent.ERROR, error);
getFavsArraySql.text = "SELECT * FROM favGames";
getFavsArraySql.execute();
var favsArr:Array = new Array();
function res(e:SQLEvent):void
{
trace("sql good!");
favsArr=getFavsArraySql.getResult().data;
}
function error(e:SQLEvent):void
{
trace("sql error!");
}
trace(favsArr);
return favsArr;
}
Assuming I understood your question, Instead of expecting getFavsGamesArray() to actually return the results from an asynchronous event (which it likely never will), consider passing a function (as an argument) to call within your res() function that would then process the data.
In your SQL helper class, we'll call it SQLHelper.as:
private var processResultsFun:Function;
public function getFavsGamesArray(callBackFun:Function):void
{
processResultsFun = callBackFun;
...
} //Do not return array, instead leave it void
function res(e:SQLEvent):void
{
trace("sql good!");
if(processResultsFun != null)
{
processResultsFun(getFavsArraySql.getResult().data);
}
}
In the class(es) that call your SQL helper class:
function processRows(results:Array):void {
//Make sure this function has an Array argument
//By the time this is called you should have some results
}
...
SQLHelper.getFavsGamesArray(processRows);
You can optionally pass an error handling function as well.
Your problem is that your task is asynchronous.
favsArris a temporary variable, and you return its value directly when getFavsGamesArray completes. At that time, the value will always be null, because the listener methods are called only after the SQL statement is complete - which will be at some time in the future.
You need some way to delay everything you are going to do with the return value, until it actually exists.
The best way to do it is to dispatch your own custom event, and add the value as a field to the event object, or to add a listener method outside of your SQL class directly to the SQLStatement - and have it do stuff with event.target.getResult().data. That way you can always be sure the value exists, when processing occurs, and you keep your SQL behavior decoupled from everything on the outside.
I would also strongly encourage you not to declare your event listeners inside functions like this: You can't clean up these listeners after the SQL statements completes!
True: Declaring a function inside a function makes it temporary. That is, it exists only for the scope of your function, and it is garbage collected when it's no longer needed - just like temporary variables. But "it is no longer needed" does not apply if you use it as an event listener! The only reason this works at all is that you don't use weak references - if you did, the functions would be garbage collected before they are even called. Since you don't, the listeners will execute. But then you can't remove them without a reference! They continue to exist, as will the SQL statement, even if you set its references to null - and you've successfully created a memory leak. Not a bad one, probably, but still...
If you really want to encapsulate your SQL behavior, that is a good thing. Just consider moving each SQL statement to a dedicated class, instead of creating one giant SQLHelper, and having your listener methods declared as member functions - it is much easier to prevent memory leaks and side effects, if you keep references to everything, and you can use these in a destroy method to clean up properly.

Pushing a function from the global state into a Lua thread

I have a C++ function, called lua_tcall, which extends the abilities of lua_pcall. When lua_tcall is called, it expects that the top value of the stack is a Lua function, much like lua_pcall does. I would like lua_tcall to be able to create a thread, and use the function on the top of the global stack as the thread's function. How do I push the function from the global state into the lua_State* that I get back from lua_newthread?
To transfer values between states, lua_xmove is better than using a shared intermediary.
To transfer a function from one lua_State to another, you must use something global to both states to store the object as an intermediary. You could use a global variable or a registry entry.