/
BalanceTransferSystem.sol
87 lines (71 loc) · 3.47 KB
/
BalanceTransferSystem.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.21;
import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
import { System } from "../../../System.sol";
import { revertWithBytes } from "../../../revertWithBytes.sol";
import { WorldResourceIdInstance } from "../../../WorldResourceId.sol";
import { AccessControl } from "../../../AccessControl.sol";
import { RESOURCE_NAMESPACE } from "../../../worldResourceTypes.sol";
import { IWorldErrors } from "../../../IWorldErrors.sol";
import { Balances } from "../../../codegen/tables/Balances.sol";
import { requireNamespace } from "../../../requireNamespace.sol";
import { LimitedCallContext } from "../LimitedCallContext.sol";
/**
* @title Balance Transfer System
* @dev A system contract that facilitates balance transfers in the World and outside of the World.
*/
contract BalanceTransferSystem is System, IWorldErrors, LimitedCallContext {
using WorldResourceIdInstance for ResourceId;
/**
* @notice Transfer balance to another namespace in the World.
* @dev Requires the caller to have access to the source namespace and ensures the destination namespace type is valid.
* @param fromNamespaceId The source namespace from which the balance will be deducted.
* @param toNamespaceId The target namespace where the balance will be added.
* @param amount The amount to transfer.
*/
function transferBalanceToNamespace(
ResourceId fromNamespaceId,
ResourceId toNamespaceId,
uint256 amount
) public virtual onlyDelegatecall {
// Require the from namespace to be a valid namespace ID
requireNamespace(fromNamespaceId);
// Require the to namespace to be a valid namespace ID
requireNamespace(toNamespaceId);
// Require the namespace to exist
AccessControl.requireExistence(toNamespaceId);
// Require caller to have access to the namespace
AccessControl.requireAccess(fromNamespaceId, _msgSender());
// Get current namespace balance
uint256 balance = Balances._get(fromNamespaceId);
// Require the balance balance to be greater or equal to the amount to transfer
if (amount > balance) revert World_InsufficientBalance(balance, amount);
// Update the balances
Balances._set(fromNamespaceId, balance - amount);
Balances._set(toNamespaceId, Balances._get(toNamespaceId) + amount);
}
/**
* @notice Transfer balance out of the World to a specific address.
* @dev Requires the caller to have access to the source namespace and ensures sufficient balance before transfer.
* @param fromNamespaceId The source namespace from which the balance will be deducted.
* @param toAddress The target address where the balance will be sent.
* @param amount The amount to transfer.
*/
function transferBalanceToAddress(
ResourceId fromNamespaceId,
address toAddress,
uint256 amount
) public virtual onlyDelegatecall {
// Require caller to have access to the namespace
AccessControl.requireAccess(fromNamespaceId, _msgSender());
// Get current namespace balance
uint256 balance = Balances._get(fromNamespaceId);
// Require the balance to be greater or equal to the amount to transfer
if (amount > balance) revert World_InsufficientBalance(balance, amount);
// Update the balances
Balances._set(fromNamespaceId, balance - amount);
// Transfer the balance to the given address, revert on failure
(bool success, bytes memory data) = payable(toAddress).call{ value: amount }("");
if (!success) revertWithBytes(data);
}
}