¡El código fuente de este contrato está verificado!
Metadatos del Contrato
Compilador
0.8.16+commit.07a7930e
Idioma
Solidity
Código Fuente del Contrato
Archivo 1 de 14: Address.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)pragmasolidity ^0.8.1;/**
* @dev Collection of functions related to the address type
*/libraryAddress{
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/functionisContract(address account) internalviewreturns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0// for contracts in construction, since the code is only stored at the end// of the constructor execution.return account.code.length>0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/functionsendValue(addresspayable recipient, uint256 amount) internal{
require(address(this).balance>= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/functionfunctionCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value
) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(address(this).balance>= value, "Address: insufficient balance for call");
(bool success, bytesmemory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target, bytesmemory data) internalviewreturns (bytesmemory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
(bool success, bytesmemory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
(bool success, bytesmemory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/functionverifyCallResultFromTarget(address target,
bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
if (success) {
if (returndata.length==0) {
// only check isContract if the call was successful and the return data is empty// otherwise we already know that it was a contractrequire(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/functionverifyCallResult(bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalpurereturns (bytesmemory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function_revert(bytesmemory returndata, stringmemory errorMessage) privatepure{
// Look for revert reason and bubble it up if presentif (returndata.length>0) {
// The easiest way to bubble the revert reason is using memory via assembly/// @solidity memory-safe-assemblyassembly {
let returndata_size :=mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
Código Fuente del Contrato
Archivo 2 de 14: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^0.8.0;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Código Fuente del Contrato
Archivo 3 de 14: CrossChainMailbox.sol
// SPDX-License-Identifier: UNLICENSEDpragmasolidity ^0.8.16;import {FeeCollector} from"contracts/src/utils/FeeCollector.sol";
import {ENSHelper} from"contracts/src/utils/ENSHelper.sol";
import {StringHelper} from"contracts/src/utils/StringHelper.sol";
import {ITelepathyRouter} from"telepathy-contracts/amb/interfaces/ITelepathy.sol";
import {TelepathyHandler} from"telepathy-contracts/amb/interfaces/TelepathyHandler.sol";
/// @title CrossChainMailer/// @author Succinct Labs/// @notice An example contract for sending messages to other chains, using the TelepathyRouter./// @dev The FeeCollector is for discouraging spam on non-mainnet chains.contractCrossChainMailerisFeeCollector, ENSHelper{
/// @notice The TelepathyRouter contract, which sends messages to other chains.
ITelepathyRouter public telepathyRouter;
constructor(address _telepathyRouter) {
telepathyRouter = ITelepathyRouter(_telepathyRouter);
}
/// @notice Sends a message to a destination mailbox./// @param _destinationChainId The chain ID where the destination CrossChainMailbox./// @param _destinationMailbox The address of the destination CrossChainMailbox./// @param _message The message to send.functionsendMail(uint32 _destinationChainId, address _destinationMailbox, bytesmemory _message)
externalpayable{
if (msg.value< fee) {
revert InsufficientFee(msg.value, fee);
}
stringmemory data = StringHelper.formatMessage(_message, msg.sender.balance, ENSHelper.getName(msg.sender));
telepathyRouter.send(_destinationChainId, _destinationMailbox, bytes(data));
}
}
/// @title CrossChainMailbox/// @author Succinct Labs/// @notice An example contract for receiving messages from other chains, using the TelepathyHandler.contractCrossChainMailboxisTelepathyHandler{
string[] public messages;
eventMessageReceived(uint32indexed sourceChainId, addressindexed sourceAddress, string message);
constructor(address _telepathyRouter) TelepathyHandler(_telepathyRouter) {}
functionhandleTelepathyImpl(uint32 _sourceChainId, address _sourceAddress, bytesmemory _message)
internaloverride{
messages.push(string(_message));
emit MessageReceived(_sourceChainId, _sourceAddress, string(_message));
}
functionmessagesLength() externalviewreturns (uint256) {
return messages.length;
}
}
Código Fuente del Contrato
Archivo 4 de 14: ENS.sol
pragmasolidity >=0.8.4;interfaceENS{
// Logged when the owner of a node assigns a new owner to a subnode.eventNewOwner(bytes32indexed node, bytes32indexed label, address owner);
// Logged when the owner of a node transfers ownership to a new account.eventTransfer(bytes32indexed node, address owner);
// Logged when the resolver for a node changes.eventNewResolver(bytes32indexed node, address resolver);
// Logged when the TTL of a node changeseventNewTTL(bytes32indexed node, uint64 ttl);
// Logged when an operator is added or removed.eventApprovalForAll(addressindexed owner,
addressindexed operator,
bool approved
);
functionsetRecord(bytes32 node,
address owner,
address resolver,
uint64 ttl
) external;
functionsetSubnodeRecord(bytes32 node,
bytes32 label,
address owner,
address resolver,
uint64 ttl
) external;
functionsetSubnodeOwner(bytes32 node,
bytes32 label,
address owner
) externalreturns (bytes32);
functionsetResolver(bytes32 node, address resolver) external;
functionsetOwner(bytes32 node, address owner) external;
functionsetTTL(bytes32 node, uint64 ttl) external;
functionsetApprovalForAll(address operator, bool approved) external;
functionowner(bytes32 node) externalviewreturns (address);
functionresolver(bytes32 node) externalviewreturns (address);
functionttl(bytes32 node) externalviewreturns (uint64);
functionrecordExists(bytes32 node) externalviewreturns (bool);
functionisApprovedForAll(address owner,
address operator
) externalviewreturns (bool);
}
Código Fuente del Contrato
Archivo 5 de 14: ENSHelper.sol
pragmasolidity ^0.8.16;import {Address} from"openzeppelin-contracts/contracts/utils/Address.sol";
import {Strings} from"openzeppelin-contracts/contracts/utils/Strings.sol";
import {ENS} from"ens-contracts/registry/ENS.sol";
import {IAddrResolver} from"ens-contracts/resolvers/profiles/IAddrResolver.sol";
import {INameResolver} from"ens-contracts/resolvers/profiles/INameResolver.sol";
contractENSHelper{
usingAddressforaddress;
usingENSNamehashforbytes;
// Same address for Mainet, Ropsten, Rinkerby, Gorli and other networks;addressconstant ensRegistryAddr =0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
/// The namehash of the `eth` TLD in the ENS registry, eg. namehash("eth").bytes32publicconstant ETH_NODE =keccak256(abi.encodePacked(bytes32(0), keccak256("eth")));
/// @notice Returns the ENS name for a given address, or an string address if no name is set./// @param _addr The address to lookup./// @return name The ENS name for the given address./// @dev For this to successfully retrieve a name, the address must have the reverse record/// set, and the forward record must match the address.functiongetName(address _addr) publicviewreturns (stringmemory name) {
if (!ensRegistryAddr.isContract()) {
return Strings.toHexString(_addr);
}
// Use reverse resolver to get the ENS name that address this has.bytes32 nodeReverse = reverseNode(_addr);
address reverseResolverAddr = ENS(ensRegistryAddr).resolver(nodeReverse);
if (reverseResolverAddr ==address(0) ||!reverseResolverAddr.isContract()) {
return Strings.toHexString(_addr);
}
name = INameResolver(reverseResolverAddr).name(nodeReverse);
if (bytes(name).length==0) {
return Strings.toHexString(_addr);
}
// ENS does not enforce the accuracy of reverse records, so you you must always perform a// forward resolution for the returned name and check it matches the original address.bytes32 nodeForward =bytes(name).namehash(0);
address forwardResolverAddr = ENS(ensRegistryAddr).resolver(nodeForward);
if (forwardResolverAddr ==address(0) ||!forwardResolverAddr.isContract()) {
return Strings.toHexString(_addr);
}
address forwardAddr = IAddrResolver(forwardResolverAddr).addr(nodeForward);
if (forwardAddr == _addr) {
return name;
} else {
return Strings.toHexString(_addr);
}
}
// Below are helper functions from ReverseRecords.sol, used so it's not necassary to maintain// a reference to the contract on each chain.// Source: https://github.com/ensdomains/reverse-records/blob/6ef80ba0a445b3f7cdff7819aaad1efbd8ad22fb/contracts/ReverseRecords.sol/// @notice This is the equivalant of namehash('addr.reverse')bytes32publicconstant ADDR_REVERSE_NODE =0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;
/// @notice Returns the node hash for a given account's reverse records.functionreverseNode(address _addr) publicpurereturns (bytes32) {
returnkeccak256(abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(_addr)));
}
functionsha3HexAddress(address addr) privatepurereturns (bytes32 ret) {
addr;
ret; // Stop warning us about unused variablesassembly {
let lookup :=0x3031323334353637383961626364656600000000000000000000000000000000for { let i :=40 } gt(i, 0) {} {
i :=sub(i, 1)
mstore8(i, byte(and(addr, 0xf), lookup))
addr :=div(addr, 0x10)
i :=sub(i, 1)
mstore8(i, byte(and(addr, 0xf), lookup))
addr :=div(addr, 0x10)
}
ret :=keccak256(0, 40)
}
}
}
/// @dev Source: https://github.com/JonahGroendal/ens-namehash/blob/d956b0be0ae5d14191067ed398c4454e35f4558d/contracts/ENSNamehash.sollibraryENSNamehash{
functionnamehash(bytesmemory domain) internalpurereturns (bytes32) {
return namehash(domain, 0);
}
functionnamehash(bytesmemory domain, uint256 i) internalpurereturns (bytes32) {
if (domain.length<= i) {
return0x0000000000000000000000000000000000000000000000000000000000000000;
}
uint256 len = LabelLength(domain, i);
returnkeccak256(abi.encodePacked(namehash(domain, i + len +1), keccak(domain, i, len)));
}
functionLabelLength(bytesmemory domain, uint256 i) privatepurereturns (uint256) {
uint256 len;
while (i + len != domain.length&& domain[i + len] !=0x2e) {
len++;
}
return len;
}
functionkeccak(bytesmemory data, uint256 offset, uint256 len) privatepurereturns (bytes32 ret) {
require(offset + len <= data.length);
assembly {
ret :=keccak256(add(add(data, 32), offset), len)
}
}
}
Código Fuente del Contrato
Archivo 6 de 14: FeeCollector.sol
pragmasolidity ^0.8.16;import {Ownable} from"openzeppelin-contracts/contracts/access/Ownable.sol";
contractFeeCollectorisOwnable{
errorInsufficientFee(uint256 actual, uint256 expected);
/// @notice The fee to pay for sending a message./// @dev The intention is only set to non-zero when deployed non-mainnet chains, used to discourage spam.uint256public fee;
/// @notice Allows owner to set a new fee./// @param _fee The new fee to use.functionsetFee(uint256 _fee) externalonlyOwner{
fee = _fee;
}
/// @notice Allows owner to claim all fees sent to this contract.functionclaimFees() externalonlyOwner{
payable(owner()).transfer(address(this).balance);
}
}
Código Fuente del Contrato
Archivo 7 de 14: IAddrResolver.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4;/**
* Interface for the legacy (ETH-only) addr function.
*/interfaceIAddrResolver{
eventAddrChanged(bytes32indexed node, address a);
/**
* Returns the address associated with an ENS node.
* @param node The ENS node to query.
* @return The associated address.
*/functionaddr(bytes32 node) externalviewreturns (addresspayable);
}
Código Fuente del Contrato
Archivo 8 de 14: INameResolver.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4;interfaceINameResolver{
eventNameChanged(bytes32indexed node, string name);
/**
* Returns the name associated with an ENS node, for reverse records.
* Defined in EIP181.
* @param node The ENS node to query.
* @return The associated name.
*/functionname(bytes32 node) externalviewreturns (stringmemory);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)pragmasolidity ^0.8.0;/**
* @dev Standard math utilities missing in the Solidity language.
*/libraryMath{
enumRounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/functionmax(uint256 a, uint256 b) internalpurereturns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/functionmin(uint256 a, uint256 b) internalpurereturns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/functionaverage(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b) / 2 can overflow.return (a & b) + (a ^ b) /2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/functionceilDiv(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.return a ==0 ? 0 : (a -1) / b +1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/functionmulDiv(uint256 x,
uint256 y,
uint256 denominator
) internalpurereturns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256// variables such that product = prod1 * 2^256 + prod0.uint256 prod0; // Least significant 256 bits of the productuint256 prod1; // Most significant 256 bits of the productassembly {
let mm :=mulmod(x, y, not(0))
prod0 :=mul(x, y)
prod1 :=sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.if (prod1 ==0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.require(denominator > prod1);
///////////////////////////////////////////////// 512 by 256 division.///////////////////////////////////////////////// Make division exact by subtracting the remainder from [prod1 prod0].uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder :=mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 :=sub(prod1, gt(remainder, prod0))
prod0 :=sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.// See https://cs.stackexchange.com/q/138556/92363.// Does not overflow because the denominator cannot be zero at this stage in the function.uint256 twos = denominator & (~denominator +1);
assembly {
// Divide denominator by twos.
denominator :=div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 :=div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos :=add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for// four bits. That is, denominator * inv = 1 mod 2^4.uint256 inverse = (3* denominator) ^2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works// in modular arithmetic, doubling the correct bits in each step.
inverse *=2- denominator * inverse; // inverse mod 2^8
inverse *=2- denominator * inverse; // inverse mod 2^16
inverse *=2- denominator * inverse; // inverse mod 2^32
inverse *=2- denominator * inverse; // inverse mod 2^64
inverse *=2- denominator * inverse; // inverse mod 2^128
inverse *=2- denominator * inverse; // inverse mod 2^256// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/functionmulDiv(uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internalpurereturns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up &&mulmod(x, y, denominator) >0) {
result +=1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/functionsqrt(uint256 a) internalpurereturns (uint256) {
if (a ==0) {
return0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.//// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.//// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`//// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.uint256 result =1<< (log2(a) >>1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision// into the expected uint128 result.unchecked {
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/functionsqrt(uint256 a, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=128;
}
if (value >>64>0) {
value >>=64;
result +=64;
}
if (value >>32>0) {
value >>=32;
result +=32;
}
if (value >>16>0) {
value >>=16;
result +=16;
}
if (value >>8>0) {
value >>=8;
result +=8;
}
if (value >>4>0) {
value >>=4;
result +=4;
}
if (value >>2>0) {
value >>=2;
result +=2;
}
if (value >>1>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result =log2(value);
return result + (rounding == Rounding.Up &&1<< result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >=10**64) {
value /=10**64;
result +=64;
}
if (value >=10**32) {
value /=10**32;
result +=32;
}
if (value >=10**16) {
value /=10**16;
result +=16;
}
if (value >=10**8) {
value /=10**8;
result +=8;
}
if (value >=10**4) {
value /=10**4;
result +=4;
}
if (value >=10**2) {
value /=10**2;
result +=2;
}
if (value >=10**1) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up &&10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/functionlog256(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=16;
}
if (value >>64>0) {
value >>=64;
result +=8;
}
if (value >>32>0) {
value >>=32;
result +=4;
}
if (value >>16>0) {
value >>=16;
result +=2;
}
if (value >>8>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog256(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up &&1<< (result <<3) < value ? 1 : 0);
}
}
}
Código Fuente del Contrato
Archivo 11 de 14: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)pragmasolidity ^0.8.0;import"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Código Fuente del Contrato
Archivo 12 de 14: StringHelper.sol
pragmasolidity ^0.8.16;import {Strings} from"openzeppelin-contracts/contracts/utils/Strings.sol";
libraryStringHelper{
/// @notice Concatenates together a formatted message./// @param _rawMessage The raw message bytes./// @param _balance The balance of the sender./// @param _ensName The ENS name of the sender ("" if none)./// @dev The formatting is like:////// 'hello, world!'/// - alice.eth (1.00 ETH)functionformatMessage(bytesmemory _rawMessage, uint256 _balance, stringmemory _ensName)
internalviewreturns (stringmemory)
{
stringmemory messageStr =string(_rawMessage);
stringmemory ethBalanceStr = formatBalance(_balance);
// Use the ENS name if it exists, otherwise use the address.stringmemory senderStr;
if (bytes(_ensName).length==0) {
senderStr = Strings.toHexString(msg.sender);
} else {
senderStr = _ensName;
}
stringmemory lineOne =string.concat(string.concat("'", messageStr), "'\n");
stringmemory lineTwo =string.concat(string.concat(string.concat(string.concat("- ", senderStr), " ("), ethBalanceStr), ")");
stringmemory data =string.concat(lineOne, lineTwo);
return data;
}
/// @notice Formats a native balance to a string with 2 decimal places and native currency/// symbol. For example, 123456789000000000000 wei would be formatted as "123.46 ETH"./// @param _balance The balance to format.functionformatBalance(uint256 _balance) publicviewreturns (stringmemory) {
uint256 integerAmount = _balance /1ether;
uint256 integerDigits;
if (integerAmount >0) {
while (true) {
if (integerAmount >=10** integerDigits) {
integerDigits++;
} else {
break;
}
}
} else {
integerDigits =1;
}
bytesmemory balanceByteArr =newbytes(integerDigits +3); // extra 3 for "." plus 2 digitsuint256 i = integerDigits;
while (i >0) {
balanceByteArr[i -1] =bytes1(uint8(48+ integerAmount %10));
integerAmount /=10;
i--;
}
balanceByteArr[integerDigits] =".";
balanceByteArr[integerDigits +1] =bytes1(uint8(48+ (_balance /1e17) %10));
balanceByteArr[integerDigits +2] =bytes1(uint8(48+ (_balance /1e16) %10));
stringmemory balanceStr =string(balanceByteArr);
// ETH for mainnet, xDAI for Gnosis, etcstringmemory currencyStr;
if (block.chainid==5) {
currencyStr =" gETH";
} elseif (block.chainid==100) {
currencyStr =" xDAI";
} elseif (block.chainid==137) {
currencyStr =" MATIC";
} else {
currencyStr =" ETH";
}
returnstring.concat(balanceStr, currencyStr);
}
}
Código Fuente del Contrato
Archivo 13 de 14: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)pragmasolidity ^0.8.0;import"./math/Math.sol";
/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant _SYMBOLS ="0123456789abcdef";
uint8privateconstant _ADDRESS_LENGTH =20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
uint256 length = Math.log10(value) +1;
stringmemory buffer =newstring(length);
uint256 ptr;
/// @solidity memory-safe-assemblyassembly {
ptr :=add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assemblyassembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /=10;
if (value ==0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
return toHexString(value, Math.log256(value) +1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = _SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/functiontoHexString(address addr) internalpurereturns (stringmemory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}