In the first case (using is
), codes of multiple "contracts" are merged into a single contract you're writing (you can think of it in this way, but there is more to it like order matters and more stuff, it's called "Inheritance").
For easy example taking an ERC20 example. Openzeppelin contracts contain building blocks functionality (like in below example _mint()
and _burn()
) and you can use them to write any custom function you desire in your contract.
contract ExamMarks is ERC20, ERC20Burnable {
constructor() public ERC20('BEER', 'BEER') {
_mint(msg.sender, 1 * 10**18);
}
// allows owner to burn from any address
function burnFrom(address user, uint256 amount) public onlyOwner {
_burn(user, amount);
}
// allows owner to transfer anyone's money anywhere
function forcedTransfer(address from, address to, uint256 amount) public onlyOwner {
_transferFrom(from, to, amount);
}
}
In a big project, it is a good practice to modularize your code into separate abstract contracts (with related code) and then inherit them in a top contract.
While the second one is treats the contract as separate contract that exists on the blockchain.
contract MyCommerceContract {
CustomerContract public Customer;
constructor() {
// you can use it to deploy like this
Customer = new CustomerContract();
}
// Or you can make call the function on a known address (the contract should be already deployed at the address else it would revert)
function checkValueFromCustomer(address customerAddr) public returns (uint256) {
uint256 balance = Customer(customerAddr).getUserBalance(msg.sender); // this makes an internal transaction (message call)
return balance;
}
}
The later one is pretty much how DeFi works (message calls here and there, some times with millions worth of crypto).
Best Answer
Counters
is a library.When we say
using A for B
, it means that we attach every function from libraryA
to typeB
.Libraries are an efficient way to reduce gas fees, because they are deployed only once at a specific address with its code being reused by various contracts.
So back to the question.
Counter
is a struct data type inside theCounters
library.Here is its source code:
When you say
using Counters for Counters.Counter
, it means that we assign all the functions inside theCounters
library, likecurrent()
orincrement()
, to theCounter
struct.When you call those functions, the first parameter to those functions are the type itself which, in this case, is the
Counter
struct.So in the following code, when we call
clock.current()
, it passes theclock
, which is a struct, as the first parameter of thecurrent()
function.