Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions COPYRIGHT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Copyright © 2025 The Stable Order <br />
All rights reserved.

All works in this repository may be used according to the conditions
stated in the LICENSE.md file available in this repository.

These works are WITHOUT ANY WARRANTY, without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Comment on lines +1 to +8
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Confirm copyright holder name + avoid HTML in markdown.
If “The Stable Order” isn’t the intended owner for this repo, this file will create legal/branding confusion; also <br /> is unnecessary in .md.

-Copyright © 2025 The Stable Order <br />
+Copyright © 2025 The Stable Order
 All rights reserved.

(If the holder should be “DjedAlliance”, “IOHK”, “Contributors”, etc., please update accordingly.)

🤖 Prompt for AI Agents
In COPYRIGHT.md around lines 1 to 8, the file uses an HTML <br /> tag and a
possibly incorrect copyright holder name (“The Stable Order”); remove the HTML
tag and replace it with plain Markdown/newline formatting, and confirm and
update the copyright holder to the correct entity (e.g., “DjedAlliance”, “IOHK”,
“Contributors”, or the proper legal owner) so the file reflects the intended
owner; keep the copyright year(s) as-is or update if required and preserve the
warranty disclaimers in plain-text Markdown.

54 changes: 34 additions & 20 deletions src/Djed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,37 +31,51 @@ contract Djed is ReentrancyGuard {
uint256 public immutable scDecimalScalingFactor;
uint256 public immutable rcDecimalScalingFactor;

struct ConstructorParams {
address oracleAddress;
uint256 scalingFactor;
address treasury;
uint256 initialTreasuryFee;
uint256 treasuryRevenueTarget;
uint256 reserveRatioMin;
uint256 reserveRatioMax;
uint256 fee;
uint256 thresholdSupplySC;
uint256 rcMinPrice;
uint256 rcInitialPrice;
uint256 txLimit;
string stableCoinName;
string stableCoinSymbol;
string reserveCoinName;
string reserveCoinSymbol;
}
Comment on lines +34 to +51
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the full context of the Djed contract, especially the constructor
head -100 src/Djed.sol | tail -70

Repository: DjedAlliance/Djed-Solidity

Length of output: 3005


🏁 Script executed:

# Search for Djed constructor instantiations in Solidity files
rg -n --type solidity -A5 'new\s+Djed\s*\('

Repository: DjedAlliance/Djed-Solidity

Length of output: 102


🏁 Script executed:

# Search for deployments in TypeScript/JavaScript files
rg -n --type ts --type js -A5 'Djed|deploy' | head -200

Repository: DjedAlliance/Djed-Solidity

Length of output: 218


🏁 Script executed:

# Check the lines 59-80 referenced in the review
sed -n '59,80p' src/Djed.sol

Repository: DjedAlliance/Djed-Solidity

Length of output: 1008


🏁 Script executed:

# Find all files in the repo to understand structure
find . -type f -name "*.sol" -o -name "*.ts" -o -name "*.js" | grep -E "(test|deploy|spec)" | head -30

Repository: DjedAlliance/Djed-Solidity

Length of output: 495


🏁 Script executed:

# Search for any Djed instantiation in .sol files
rg -n "new Djed" --glob "*.sol"

Repository: DjedAlliance/Djed-Solidity

Length of output: 492


🏁 Script executed:

# Search for Djed in test/deployment context (TypeScript/JavaScript)
rg -n "Djed" --glob "*.ts" --glob "*.js" -A 3 | head -100

Repository: DjedAlliance/Djed-Solidity

Length of output: 218


🏁 Script executed:

# Check if there are any comments or documentation about constructor changes
rg -n "constructor|ConstructorParams" --glob "*.sol" -B2 -A2

Repository: DjedAlliance/Djed-Solidity

Length of output: 4358


🏁 Script executed:

# Check the exact constructor calls in test files
sed -n '18,30p' src/test/Djed.t.sol

Repository: DjedAlliance/Djed-Solidity

Length of output: 495


🏁 Script executed:

# Check Fee test
sed -n '25,40p' src/test/Fee.t.sol

Repository: DjedAlliance/Djed-Solidity

Length of output: 590


🏁 Script executed:

# Check TransactionLimit test
sed -n '21,35p' src/test/TransactionLimit.t.sol

Repository: DjedAlliance/Djed-Solidity

Length of output: 548


🏁 Script executed:

# Check deployment script
sed -n '29,50p' scripts/deployDjedContract.s.sol

Repository: DjedAlliance/Djed-Solidity

Length of output: 659


🏁 Script executed:

# Compare with DjedShu constructor which uses individual params
sed -n '40,60p' src/DjedShu.sol

Repository: DjedAlliance/Djed-Solidity

Length of output: 1011


Update all Djed constructor calls to use struct parameter format.

The constructor was changed to accept ConstructorParams memory params instead of individual parameters. All instantiations must be updated to pass a struct:

Currently broken in:

  • src/test/Djed.t.sol:18-30
  • src/test/Fee.t.sol:25-37
  • src/test/TransactionLimit.t.sol:21-34
  • scripts/deployDjedContract.s.sol:29-41

Each call passes positional arguments but must instead create a struct instance. Example fix:

Djed.ConstructorParams({
    oracleAddress: address(oracle),
    scalingFactor: SCALING_FACTOR,
    treasury: TREASURY,
    // ... other fields
})
🤖 Prompt for AI Agents
In src/Djed.sol around lines 34 to 51 the constructor signature was changed to
accept a single ConstructorParams memory params struct, but tests and deploy
scripts still call the constructor with positional arguments; update all
instantiations in src/test/Djed.t.sol (lines ~18-30), src/test/Fee.t.sol
(25-37), src/test/TransactionLimit.t.sol (21-34) and
scripts/deployDjedContract.s.sol (29-41) to pass a Djed.ConstructorParams struct
literal instead of positional parameters (e.g. Djed.ConstructorParams({
oracleAddress: address(oracle), scalingFactor: SCALING_FACTOR, treasury:
TREASURY, initialTreasuryFee: ..., treasuryRevenueTarget: ..., reserveRatioMin:
..., reserveRatioMax: ..., fee: ..., thresholdSupplySC: ..., rcMinPrice: ...,
rcInitialPrice: ..., txLimit: ..., stableCoinName: "...", stableCoinSymbol:
"...", reserveCoinName: "...", reserveCoinSymbol: "..." })), ensure all fields
are provided with the correct names and types and update imports/qualified name
if needed so the contract compiles.


event BoughtStableCoins(address indexed buyer, address indexed receiver, uint256 amountSC, uint256 amountBC);
event SoldStableCoins(address indexed seller, address indexed receiver, uint256 amountSC, uint256 amountBC);
event BoughtReserveCoins(address indexed buyer, address indexed receiver, uint256 amountRC, uint256 amountBC);
event SoldReserveCoins(address indexed seller, address indexed receiver, uint256 amountRC, uint256 amountBC);
event SoldBothCoins(address indexed seller, address indexed receiver, uint256 amountSC, uint256 amountRC, uint256 amountBC);

constructor(
address oracleAddress, uint256 _scalingFactor,
address _treasury, uint256 _initialTreasuryFee, uint256 _treasuryRevenueTarget,
uint256 _reserveRatioMin, uint256 _reserveRatioMax,
uint256 _fee, uint256 _thresholdSupplySC, uint256 _rcMinPrice, uint256 _rcInitialPrice, uint256 _txLimit
) payable {
stableCoin = new Coin("StableCoin", "SC");
reserveCoin = new Coin("ReserveCoin", "RC");
constructor(ConstructorParams memory params) payable {
stableCoin = new Coin(params.stableCoinName, params.stableCoinSymbol);
reserveCoin = new Coin(params.reserveCoinName, params.reserveCoinSymbol);
scDecimalScalingFactor = 10**stableCoin.decimals();
rcDecimalScalingFactor = 10**reserveCoin.decimals();
scalingFactor = _scalingFactor;
scalingFactor = params.scalingFactor;

treasury = _treasury;
initialTreasuryFee = _initialTreasuryFee;
treasuryRevenueTarget = _treasuryRevenueTarget;
treasury = params.treasury;
initialTreasuryFee = params.initialTreasuryFee;
treasuryRevenueTarget = params.treasuryRevenueTarget;

reserveRatioMin = _reserveRatioMin;
reserveRatioMax = _reserveRatioMax;
fee = _fee;
thresholdSupplySC = _thresholdSupplySC;
rcMinPrice = _rcMinPrice;
rcInitialPrice = _rcInitialPrice;
txLimit = _txLimit;
reserveRatioMin = params.reserveRatioMin;
reserveRatioMax = params.reserveRatioMax;
fee = params.fee;
thresholdSupplySC = params.thresholdSupplySC;
rcMinPrice = params.rcMinPrice;
rcInitialPrice = params.rcInitialPrice;
txLimit = params.txLimit;

oracle = IOracle(oracleAddress);
oracle = IOracle(params.oracleAddress);
oracle.acceptTermsOfService();
}
Comment on lines +59 to 80
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add constructor parameter validation (prevents div-by-zero + bad deployments).
Right now any of these can silently deploy a broken instance (e.g., treasuryRevenueTarget == 0 makes treasuryFee() divide-by-zero; scalingFactor == 0 breaks fee math; zero addresses burn funds / break oracle).

 constructor(ConstructorParams memory params) payable {
+    require(params.oracleAddress != address(0), "ctor: oracle=0");
+    require(params.treasury != address(0), "ctor: treasury=0");
+    require(params.scalingFactor > 0, "ctor: scalingFactor=0");
+    require(params.treasuryRevenueTarget > 0, "ctor: revenueTarget=0");
+    require(params.reserveRatioMin <= params.reserveRatioMax, "ctor: rrMin>rrMax");
+    require(params.txLimit > 0, "ctor: txLimit=0");
+    require(bytes(params.stableCoinName).length != 0, "ctor: scName empty");
+    require(bytes(params.stableCoinSymbol).length != 0, "ctor: scSymbol empty");
+    require(bytes(params.reserveCoinName).length != 0, "ctor: rcName empty");
+    require(bytes(params.reserveCoinSymbol).length != 0, "ctor: rcSymbol empty");
+    require(params.rcMinPrice > 0, "ctor: rcMinPrice=0");
+    require(params.rcInitialPrice > 0, "ctor: rcInitialPrice=0");
+    require(params.rcMinPrice <= params.rcInitialPrice, "ctor: rcMin>rcInit");
     stableCoin = new Coin(params.stableCoinName, params.stableCoinSymbol);
     reserveCoin = new Coin(params.reserveCoinName, params.reserveCoinSymbol);
     scDecimalScalingFactor = 10**stableCoin.decimals();
     rcDecimalScalingFactor = 10**reserveCoin.decimals();
     scalingFactor = params.scalingFactor;
     ...
 }
🤖 Prompt for AI Agents
In src/Djed.sol around lines 59 to 80, add input validation in the constructor
to prevent bad deployments and divide-by-zero: require non-zero addresses for
treasury and oracle (check oracleAddress != address(0) before assigning and
calling acceptTermsOfService), require numeric parameters used as divisors or
scaling factors to be > 0 (treasuryRevenueTarget > 0, scalingFactor > 0,
scDecimalScalingFactor and rcDecimalScalingFactor should be checked or derive
safely), require sensible positive bounds for prices and limits (rcMinPrice > 0,
rcInitialPrice > 0, txLimit > 0), enforce reserveRatioMin/Max consistency (0 <
reserveRatioMin <= reserveRatioMax and reserveRatioMax within expected max), and
validate fee/initialTreasuryFee are within expected ranges; use require(...)
with clear error messages before any state changes or external calls so the
contract cannot deploy with invalid params.


Expand Down